mirror of
https://github.com/samuelclay/NewsBlur.git
synced 2025-09-18 21:50:56 +00:00
Adding String HTML decoding class to iphone app. Also working on paging, but it needs scroll love.
This commit is contained in:
parent
27f0cb8ee3
commit
86741fbed4
8 changed files with 3966 additions and 1971 deletions
|
@ -111,7 +111,9 @@
|
|||
[appDelegate addActiveFeedStories:[results objectForKey:@"stories"]];
|
||||
}
|
||||
NSLog(@"Stories: %d on page %d", [appDelegate.activeFeedStories count], self.feedPage);
|
||||
[[self storyTitlesTable] reloadData];
|
||||
|
||||
// NSArray *indexPaths = [NSArray alloc]
|
||||
// [self.storyTitlesTable insertRowsAtIndexPaths:indexPaths withRowAnimation:NO];
|
||||
self.pageFetching = NO;
|
||||
[results release];
|
||||
[jsonS release];
|
||||
|
|
351
media/iphone/GTMDefines.h
Normal file
351
media/iphone/GTMDefines.h
Normal file
|
@ -0,0 +1,351 @@
|
|||
//
|
||||
// GTMDefines.h
|
||||
//
|
||||
// Copyright 2008 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
// of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations under
|
||||
// the License.
|
||||
//
|
||||
|
||||
// ============================================================================
|
||||
|
||||
#include <AvailabilityMacros.h>
|
||||
#include <TargetConditionals.h>
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
#include <Availability.h>
|
||||
#endif // TARGET_OS_IPHONE
|
||||
|
||||
// Not all MAC_OS_X_VERSION_10_X macros defined in past SDKs
|
||||
#ifndef MAC_OS_X_VERSION_10_5
|
||||
#define MAC_OS_X_VERSION_10_5 1050
|
||||
#endif
|
||||
#ifndef MAC_OS_X_VERSION_10_6
|
||||
#define MAC_OS_X_VERSION_10_6 1060
|
||||
#endif
|
||||
|
||||
// Not all __IPHONE_X macros defined in past SDKs
|
||||
#ifndef __IPHONE_2_1
|
||||
#define __IPHONE_2_1 20100
|
||||
#endif
|
||||
#ifndef __IPHONE_2_2
|
||||
#define __IPHONE_2_2 20200
|
||||
#endif
|
||||
#ifndef __IPHONE_3_0
|
||||
#define __IPHONE_3_0 30000
|
||||
#endif
|
||||
#ifndef __IPHONE_3_1
|
||||
#define __IPHONE_3_1 30100
|
||||
#endif
|
||||
#ifndef __IPHONE_3_2
|
||||
#define __IPHONE_3_2 30200
|
||||
#endif
|
||||
#ifndef __IPHONE_4_0
|
||||
#define __IPHONE_4_0 40000
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CPP symbols that can be overridden in a prefix to control how the toolbox
|
||||
// is compiled.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and
|
||||
// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens
|
||||
// when a validation fails. If you implement your own validators, you may want
|
||||
// to control their internals using the same macros for consistency.
|
||||
#ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT
|
||||
#define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0
|
||||
#endif
|
||||
|
||||
// Give ourselves a consistent way to do inlines. Apple's macros even use
|
||||
// a few different actual definitions, so we're based off of the foundation
|
||||
// one.
|
||||
#if !defined(GTM_INLINE)
|
||||
#if defined (__GNUC__) && (__GNUC__ == 4)
|
||||
#define GTM_INLINE static __inline__ __attribute__((always_inline))
|
||||
#else
|
||||
#define GTM_INLINE static __inline__
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Give ourselves a consistent way of doing externs that links up nicely
|
||||
// when mixing objc and objc++
|
||||
#if !defined (GTM_EXTERN)
|
||||
#if defined __cplusplus
|
||||
#define GTM_EXTERN extern "C"
|
||||
#else
|
||||
#define GTM_EXTERN extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Give ourselves a consistent way of exporting things if we have visibility
|
||||
// set to hidden.
|
||||
#if !defined (GTM_EXPORT)
|
||||
#define GTM_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
// _GTMDevLog & _GTMDevAssert
|
||||
//
|
||||
// _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for
|
||||
// developer level errors. This implementation simply macros to NSLog/NSAssert.
|
||||
// It is not intended to be a general logging/reporting system.
|
||||
//
|
||||
// Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert
|
||||
// for a little more background on the usage of these macros.
|
||||
//
|
||||
// _GTMDevLog log some error/problem in debug builds
|
||||
// _GTMDevAssert assert if conditon isn't met w/in a method/function
|
||||
// in all builds.
|
||||
//
|
||||
// To replace this system, just provide different macro definitions in your
|
||||
// prefix header. Remember, any implementation you provide *must* be thread
|
||||
// safe since this could be called by anything in what ever situtation it has
|
||||
// been placed in.
|
||||
//
|
||||
|
||||
// We only define the simple macros if nothing else has defined this.
|
||||
#ifndef _GTMDevLog
|
||||
|
||||
#ifdef DEBUG
|
||||
#define _GTMDevLog(...) NSLog(__VA_ARGS__)
|
||||
#else
|
||||
#define _GTMDevLog(...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif // _GTMDevLog
|
||||
|
||||
// Declared here so that it can easily be used for logging tracking if
|
||||
// necessary. See GTMUnitTestDevLog.h for details.
|
||||
@class NSString;
|
||||
GTM_EXTERN void _GTMUnitTestDevLog(NSString *format, ...);
|
||||
|
||||
#ifndef _GTMDevAssert
|
||||
// we directly invoke the NSAssert handler so we can pass on the varargs
|
||||
// (NSAssert doesn't have a macro we can use that takes varargs)
|
||||
#if !defined(NS_BLOCK_ASSERTIONS)
|
||||
#define _GTMDevAssert(condition, ...) \
|
||||
do { \
|
||||
if (!(condition)) { \
|
||||
[[NSAssertionHandler currentHandler] \
|
||||
handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \
|
||||
file:[NSString stringWithUTF8String:__FILE__] \
|
||||
lineNumber:__LINE__ \
|
||||
description:__VA_ARGS__]; \
|
||||
} \
|
||||
} while(0)
|
||||
#else // !defined(NS_BLOCK_ASSERTIONS)
|
||||
#define _GTMDevAssert(condition, ...) do { } while (0)
|
||||
#endif // !defined(NS_BLOCK_ASSERTIONS)
|
||||
|
||||
#endif // _GTMDevAssert
|
||||
|
||||
// _GTMCompileAssert
|
||||
// _GTMCompileAssert is an assert that is meant to fire at compile time if you
|
||||
// want to check things at compile instead of runtime. For example if you
|
||||
// want to check that a wchar is 4 bytes instead of 2 you would use
|
||||
// _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X)
|
||||
// Note that the second "arg" is not in quotes, and must be a valid processor
|
||||
// symbol in it's own right (no spaces, punctuation etc).
|
||||
|
||||
// Wrapping this in an #ifndef allows external groups to define their own
|
||||
// compile time assert scheme.
|
||||
#ifndef _GTMCompileAssert
|
||||
// We got this technique from here:
|
||||
// http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html
|
||||
|
||||
#define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg
|
||||
#define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg)
|
||||
#define _GTMCompileAssert(test, msg) \
|
||||
typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
|
||||
#endif // _GTMCompileAssert
|
||||
|
||||
// Macro to allow you to create NSStrings out of other macros.
|
||||
// #define FOO foo
|
||||
// NSString *fooString = GTM_NSSTRINGIFY(FOO);
|
||||
#if !defined (GTM_NSSTRINGIFY)
|
||||
#define GTM_NSSTRINGIFY_INNER(x) @#x
|
||||
#define GTM_NSSTRINGIFY(x) GTM_NSSTRINGIFY_INNER(x)
|
||||
#endif
|
||||
|
||||
// Macro to allow fast enumeration when building for 10.5 or later, and
|
||||
// reliance on NSEnumerator for 10.4. Remember, NSDictionary w/ FastEnumeration
|
||||
// does keys, so pick the right thing, nothing is done on the FastEnumeration
|
||||
// side to be sure you're getting what you wanted.
|
||||
#ifndef GTM_FOREACH_OBJECT
|
||||
#if TARGET_OS_IPHONE || !(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5)
|
||||
#define GTM_FOREACH_ENUMEREE(element, enumeration) \
|
||||
for (element in enumeration)
|
||||
#define GTM_FOREACH_OBJECT(element, collection) \
|
||||
for (element in collection)
|
||||
#define GTM_FOREACH_KEY(element, collection) \
|
||||
for (element in collection)
|
||||
#else
|
||||
#define GTM_FOREACH_ENUMEREE(element, enumeration) \
|
||||
for (NSEnumerator *_ ## element ## _enum = enumeration; \
|
||||
(element = [_ ## element ## _enum nextObject]) != nil; )
|
||||
#define GTM_FOREACH_OBJECT(element, collection) \
|
||||
GTM_FOREACH_ENUMEREE(element, [collection objectEnumerator])
|
||||
#define GTM_FOREACH_KEY(element, collection) \
|
||||
GTM_FOREACH_ENUMEREE(element, [collection keyEnumerator])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CPP symbols defined based on the project settings so the GTM code has
|
||||
// simple things to test against w/o scattering the knowledge of project
|
||||
// setting through all the code.
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Provide a single constant CPP symbol that all of GTM uses for ifdefing
|
||||
// iPhone code.
|
||||
#if TARGET_OS_IPHONE // iPhone SDK
|
||||
// For iPhone specific stuff
|
||||
#define GTM_IPHONE_SDK 1
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
#define GTM_IPHONE_SIMULATOR 1
|
||||
#else
|
||||
#define GTM_IPHONE_DEVICE 1
|
||||
#endif // TARGET_IPHONE_SIMULATOR
|
||||
#else
|
||||
// For MacOS specific stuff
|
||||
#define GTM_MACOS_SDK 1
|
||||
#endif
|
||||
|
||||
// Some of our own availability macros
|
||||
#if GTM_MACOS_SDK
|
||||
#define GTM_AVAILABLE_ONLY_ON_IPHONE UNAVAILABLE_ATTRIBUTE
|
||||
#define GTM_AVAILABLE_ONLY_ON_MACOS
|
||||
#else
|
||||
#define GTM_AVAILABLE_ONLY_ON_IPHONE
|
||||
#define GTM_AVAILABLE_ONLY_ON_MACOS UNAVAILABLE_ATTRIBUTE
|
||||
#endif
|
||||
|
||||
// Provide a symbol to include/exclude extra code for GC support. (This mainly
|
||||
// just controls the inclusion of finalize methods).
|
||||
#ifndef GTM_SUPPORT_GC
|
||||
#if GTM_IPHONE_SDK
|
||||
// iPhone never needs GC
|
||||
#define GTM_SUPPORT_GC 0
|
||||
#else
|
||||
// We can't find a symbol to tell if GC is supported/required, so best we
|
||||
// do on Mac targets is include it if we're on 10.5 or later.
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
|
||||
#define GTM_SUPPORT_GC 0
|
||||
#else
|
||||
#define GTM_SUPPORT_GC 1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// To simplify support for 64bit (and Leopard in general), we provide the type
|
||||
// defines for non Leopard SDKs
|
||||
#if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
|
||||
// NSInteger/NSUInteger and Max/Mins
|
||||
#ifndef NSINTEGER_DEFINED
|
||||
#if __LP64__ || NS_BUILD_32_LIKE_64
|
||||
typedef long NSInteger;
|
||||
typedef unsigned long NSUInteger;
|
||||
#else
|
||||
typedef int NSInteger;
|
||||
typedef unsigned int NSUInteger;
|
||||
#endif
|
||||
#define NSIntegerMax LONG_MAX
|
||||
#define NSIntegerMin LONG_MIN
|
||||
#define NSUIntegerMax ULONG_MAX
|
||||
#define NSINTEGER_DEFINED 1
|
||||
#endif // NSINTEGER_DEFINED
|
||||
// CGFloat
|
||||
#ifndef CGFLOAT_DEFINED
|
||||
#if defined(__LP64__) && __LP64__
|
||||
// This really is an untested path (64bit on Tiger?)
|
||||
typedef double CGFloat;
|
||||
#define CGFLOAT_MIN DBL_MIN
|
||||
#define CGFLOAT_MAX DBL_MAX
|
||||
#define CGFLOAT_IS_DOUBLE 1
|
||||
#else /* !defined(__LP64__) || !__LP64__ */
|
||||
typedef float CGFloat;
|
||||
#define CGFLOAT_MIN FLT_MIN
|
||||
#define CGFLOAT_MAX FLT_MAX
|
||||
#define CGFLOAT_IS_DOUBLE 0
|
||||
#endif /* !defined(__LP64__) || !__LP64__ */
|
||||
#define CGFLOAT_DEFINED 1
|
||||
#endif // CGFLOAT_DEFINED
|
||||
#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
|
||||
|
||||
// Some support for advanced clang static analysis functionality
|
||||
// See http://clang-analyzer.llvm.org/annotations.html
|
||||
#ifndef __has_feature // Optional.
|
||||
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
|
||||
#endif
|
||||
|
||||
#ifndef NS_RETURNS_RETAINED
|
||||
#if __has_feature(attribute_ns_returns_retained)
|
||||
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
|
||||
#else
|
||||
#define NS_RETURNS_RETAINED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NS_RETURNS_NOT_RETAINED
|
||||
#if __has_feature(attribute_ns_returns_not_retained)
|
||||
#define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained))
|
||||
#else
|
||||
#define NS_RETURNS_NOT_RETAINED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CF_RETURNS_RETAINED
|
||||
#if __has_feature(attribute_cf_returns_retained)
|
||||
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
|
||||
#else
|
||||
#define CF_RETURNS_RETAINED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CF_RETURNS_NOT_RETAINED
|
||||
#if __has_feature(attribute_cf_returns_not_retained)
|
||||
#define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained))
|
||||
#else
|
||||
#define CF_RETURNS_NOT_RETAINED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Defined on 10.6 and above.
|
||||
#ifndef NS_FORMAT_ARGUMENT
|
||||
#define NS_FORMAT_ARGUMENT(A)
|
||||
#endif
|
||||
|
||||
// Defined on 10.6 and above.
|
||||
#ifndef NS_FORMAT_FUNCTION
|
||||
#define NS_FORMAT_FUNCTION(F,A)
|
||||
#endif
|
||||
|
||||
#ifndef GTM_NONNULL
|
||||
#define GTM_NONNULL(x) __attribute__((nonnull(x)))
|
||||
#endif
|
||||
|
||||
// To simplify support for both Leopard and Snow Leopard we declare
|
||||
// the Snow Leopard protocols that we need here.
|
||||
#if !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
|
||||
#define GTM_10_6_PROTOCOLS_DEFINED 1
|
||||
@protocol NSConnectionDelegate
|
||||
@end
|
||||
@protocol NSAnimationDelegate
|
||||
@end
|
||||
@protocol NSImageDelegate
|
||||
@end
|
||||
@protocol NSTabViewDelegate
|
||||
@end
|
||||
#endif // !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6)
|
66
media/iphone/GTMNString+HTML.h
Normal file
66
media/iphone/GTMNString+HTML.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// GTMNSString+HTML.h
|
||||
// Dealing with NSStrings that contain HTML
|
||||
//
|
||||
// Copyright 2006-2008 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
// of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations under
|
||||
// the License.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/// Utilities for NSStrings containing HTML
|
||||
@interface NSString (GTMNSStringHTMLAdditions)
|
||||
|
||||
/// Get a string where internal characters that need escaping for HTML are escaped
|
||||
//
|
||||
/// For example, '&' become '&'. This will only cover characters from table
|
||||
/// A.2.2 of http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters
|
||||
/// which is what you want for a unicode encoded webpage. If you have a ascii
|
||||
/// or non-encoded webpage, please use stringByEscapingAsciiHTML which will
|
||||
/// encode all characters.
|
||||
///
|
||||
/// For obvious reasons this call is only safe once.
|
||||
//
|
||||
// Returns:
|
||||
// Autoreleased NSString
|
||||
//
|
||||
- (NSString *)gtm_stringByEscapingForHTML;
|
||||
|
||||
/// Get a string where internal characters that need escaping for HTML are escaped
|
||||
//
|
||||
/// For example, '&' become '&'
|
||||
/// All non-mapped characters (unicode that don't have a &keyword; mapping)
|
||||
/// will be converted to the appropriate &#xxx; value. If your webpage is
|
||||
/// unicode encoded (UTF16 or UTF8) use stringByEscapingHTML instead as it is
|
||||
/// faster, and produces less bloated and more readable HTML (as long as you
|
||||
/// are using a unicode compliant HTML reader).
|
||||
///
|
||||
/// For obvious reasons this call is only safe once.
|
||||
//
|
||||
// Returns:
|
||||
// Autoreleased NSString
|
||||
//
|
||||
- (NSString *)gtm_stringByEscapingForAsciiHTML;
|
||||
|
||||
/// Get a string where internal characters that are escaped for HTML are unescaped
|
||||
//
|
||||
/// For example, '&' becomes '&'
|
||||
/// Handles   and 2 cases as well
|
||||
///
|
||||
// Returns:
|
||||
// Autoreleased NSString
|
||||
//
|
||||
- (NSString *)gtm_stringByUnescapingFromHTML;
|
||||
|
||||
@end
|
522
media/iphone/GTMNString+HTML.m
Normal file
522
media/iphone/GTMNString+HTML.m
Normal file
|
@ -0,0 +1,522 @@
|
|||
//
|
||||
// GTMNSString+HTML.m
|
||||
// Dealing with NSStrings that contain HTML
|
||||
//
|
||||
// Copyright 2006-2008 Google Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
// use this file except in compliance with the License. You may obtain a copy
|
||||
// of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations under
|
||||
// the License.
|
||||
//
|
||||
|
||||
#import "GTMDefines.h"
|
||||
#import "GTMNString+HTML.h"
|
||||
|
||||
typedef struct {
|
||||
NSString *escapeSequence;
|
||||
unichar uchar;
|
||||
} HTMLEscapeMap;
|
||||
|
||||
// Taken from http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters
|
||||
// Ordered by uchar lowest to highest for bsearching
|
||||
static HTMLEscapeMap gAsciiHTMLEscapeMap[] = {
|
||||
// A.2.2. Special characters
|
||||
{ @""", 34 },
|
||||
{ @"&", 38 },
|
||||
{ @"'", 39 },
|
||||
{ @"<", 60 },
|
||||
{ @">", 62 },
|
||||
|
||||
// A.2.1. Latin-1 characters
|
||||
{ @" ", 160 },
|
||||
{ @"¡", 161 },
|
||||
{ @"¢", 162 },
|
||||
{ @"£", 163 },
|
||||
{ @"¤", 164 },
|
||||
{ @"¥", 165 },
|
||||
{ @"¦", 166 },
|
||||
{ @"§", 167 },
|
||||
{ @"¨", 168 },
|
||||
{ @"©", 169 },
|
||||
{ @"ª", 170 },
|
||||
{ @"«", 171 },
|
||||
{ @"¬", 172 },
|
||||
{ @"­", 173 },
|
||||
{ @"®", 174 },
|
||||
{ @"¯", 175 },
|
||||
{ @"°", 176 },
|
||||
{ @"±", 177 },
|
||||
{ @"²", 178 },
|
||||
{ @"³", 179 },
|
||||
{ @"´", 180 },
|
||||
{ @"µ", 181 },
|
||||
{ @"¶", 182 },
|
||||
{ @"·", 183 },
|
||||
{ @"¸", 184 },
|
||||
{ @"¹", 185 },
|
||||
{ @"º", 186 },
|
||||
{ @"»", 187 },
|
||||
{ @"¼", 188 },
|
||||
{ @"½", 189 },
|
||||
{ @"¾", 190 },
|
||||
{ @"¿", 191 },
|
||||
{ @"À", 192 },
|
||||
{ @"Á", 193 },
|
||||
{ @"Â", 194 },
|
||||
{ @"Ã", 195 },
|
||||
{ @"Ä", 196 },
|
||||
{ @"Å", 197 },
|
||||
{ @"Æ", 198 },
|
||||
{ @"Ç", 199 },
|
||||
{ @"È", 200 },
|
||||
{ @"É", 201 },
|
||||
{ @"Ê", 202 },
|
||||
{ @"Ë", 203 },
|
||||
{ @"Ì", 204 },
|
||||
{ @"Í", 205 },
|
||||
{ @"Î", 206 },
|
||||
{ @"Ï", 207 },
|
||||
{ @"Ð", 208 },
|
||||
{ @"Ñ", 209 },
|
||||
{ @"Ò", 210 },
|
||||
{ @"Ó", 211 },
|
||||
{ @"Ô", 212 },
|
||||
{ @"Õ", 213 },
|
||||
{ @"Ö", 214 },
|
||||
{ @"×", 215 },
|
||||
{ @"Ø", 216 },
|
||||
{ @"Ù", 217 },
|
||||
{ @"Ú", 218 },
|
||||
{ @"Û", 219 },
|
||||
{ @"Ü", 220 },
|
||||
{ @"Ý", 221 },
|
||||
{ @"Þ", 222 },
|
||||
{ @"ß", 223 },
|
||||
{ @"à", 224 },
|
||||
{ @"á", 225 },
|
||||
{ @"â", 226 },
|
||||
{ @"ã", 227 },
|
||||
{ @"ä", 228 },
|
||||
{ @"å", 229 },
|
||||
{ @"æ", 230 },
|
||||
{ @"ç", 231 },
|
||||
{ @"è", 232 },
|
||||
{ @"é", 233 },
|
||||
{ @"ê", 234 },
|
||||
{ @"ë", 235 },
|
||||
{ @"ì", 236 },
|
||||
{ @"í", 237 },
|
||||
{ @"î", 238 },
|
||||
{ @"ï", 239 },
|
||||
{ @"ð", 240 },
|
||||
{ @"ñ", 241 },
|
||||
{ @"ò", 242 },
|
||||
{ @"ó", 243 },
|
||||
{ @"ô", 244 },
|
||||
{ @"õ", 245 },
|
||||
{ @"ö", 246 },
|
||||
{ @"÷", 247 },
|
||||
{ @"ø", 248 },
|
||||
{ @"ù", 249 },
|
||||
{ @"ú", 250 },
|
||||
{ @"û", 251 },
|
||||
{ @"ü", 252 },
|
||||
{ @"ý", 253 },
|
||||
{ @"þ", 254 },
|
||||
{ @"ÿ", 255 },
|
||||
|
||||
// A.2.2. Special characters cont'd
|
||||
{ @"Œ", 338 },
|
||||
{ @"œ", 339 },
|
||||
{ @"Š", 352 },
|
||||
{ @"š", 353 },
|
||||
{ @"Ÿ", 376 },
|
||||
|
||||
// A.2.3. Symbols
|
||||
{ @"ƒ", 402 },
|
||||
|
||||
// A.2.2. Special characters cont'd
|
||||
{ @"ˆ", 710 },
|
||||
{ @"˜", 732 },
|
||||
|
||||
// A.2.3. Symbols cont'd
|
||||
{ @"Α", 913 },
|
||||
{ @"Β", 914 },
|
||||
{ @"Γ", 915 },
|
||||
{ @"Δ", 916 },
|
||||
{ @"Ε", 917 },
|
||||
{ @"Ζ", 918 },
|
||||
{ @"Η", 919 },
|
||||
{ @"Θ", 920 },
|
||||
{ @"Ι", 921 },
|
||||
{ @"Κ", 922 },
|
||||
{ @"Λ", 923 },
|
||||
{ @"Μ", 924 },
|
||||
{ @"Ν", 925 },
|
||||
{ @"Ξ", 926 },
|
||||
{ @"Ο", 927 },
|
||||
{ @"Π", 928 },
|
||||
{ @"Ρ", 929 },
|
||||
{ @"Σ", 931 },
|
||||
{ @"Τ", 932 },
|
||||
{ @"Υ", 933 },
|
||||
{ @"Φ", 934 },
|
||||
{ @"Χ", 935 },
|
||||
{ @"Ψ", 936 },
|
||||
{ @"Ω", 937 },
|
||||
{ @"α", 945 },
|
||||
{ @"β", 946 },
|
||||
{ @"γ", 947 },
|
||||
{ @"δ", 948 },
|
||||
{ @"ε", 949 },
|
||||
{ @"ζ", 950 },
|
||||
{ @"η", 951 },
|
||||
{ @"θ", 952 },
|
||||
{ @"ι", 953 },
|
||||
{ @"κ", 954 },
|
||||
{ @"λ", 955 },
|
||||
{ @"μ", 956 },
|
||||
{ @"ν", 957 },
|
||||
{ @"ξ", 958 },
|
||||
{ @"ο", 959 },
|
||||
{ @"π", 960 },
|
||||
{ @"ρ", 961 },
|
||||
{ @"ς", 962 },
|
||||
{ @"σ", 963 },
|
||||
{ @"τ", 964 },
|
||||
{ @"υ", 965 },
|
||||
{ @"φ", 966 },
|
||||
{ @"χ", 967 },
|
||||
{ @"ψ", 968 },
|
||||
{ @"ω", 969 },
|
||||
{ @"ϑ", 977 },
|
||||
{ @"ϒ", 978 },
|
||||
{ @"ϖ", 982 },
|
||||
|
||||
// A.2.2. Special characters cont'd
|
||||
{ @" ", 8194 },
|
||||
{ @" ", 8195 },
|
||||
{ @" ", 8201 },
|
||||
{ @"‌", 8204 },
|
||||
{ @"‍", 8205 },
|
||||
{ @"‎", 8206 },
|
||||
{ @"‏", 8207 },
|
||||
{ @"–", 8211 },
|
||||
{ @"—", 8212 },
|
||||
{ @"‘", 8216 },
|
||||
{ @"’", 8217 },
|
||||
{ @"‚", 8218 },
|
||||
{ @"“", 8220 },
|
||||
{ @"”", 8221 },
|
||||
{ @"„", 8222 },
|
||||
{ @"†", 8224 },
|
||||
{ @"‡", 8225 },
|
||||
// A.2.3. Symbols cont'd
|
||||
{ @"•", 8226 },
|
||||
{ @"…", 8230 },
|
||||
|
||||
// A.2.2. Special characters cont'd
|
||||
{ @"‰", 8240 },
|
||||
|
||||
// A.2.3. Symbols cont'd
|
||||
{ @"′", 8242 },
|
||||
{ @"″", 8243 },
|
||||
|
||||
// A.2.2. Special characters cont'd
|
||||
{ @"‹", 8249 },
|
||||
{ @"›", 8250 },
|
||||
|
||||
// A.2.3. Symbols cont'd
|
||||
{ @"‾", 8254 },
|
||||
{ @"⁄", 8260 },
|
||||
|
||||
// A.2.2. Special characters cont'd
|
||||
{ @"€", 8364 },
|
||||
|
||||
// A.2.3. Symbols cont'd
|
||||
{ @"ℑ", 8465 },
|
||||
{ @"℘", 8472 },
|
||||
{ @"ℜ", 8476 },
|
||||
{ @"™", 8482 },
|
||||
{ @"ℵ", 8501 },
|
||||
{ @"←", 8592 },
|
||||
{ @"↑", 8593 },
|
||||
{ @"→", 8594 },
|
||||
{ @"↓", 8595 },
|
||||
{ @"↔", 8596 },
|
||||
{ @"↵", 8629 },
|
||||
{ @"⇐", 8656 },
|
||||
{ @"⇑", 8657 },
|
||||
{ @"⇒", 8658 },
|
||||
{ @"⇓", 8659 },
|
||||
{ @"⇔", 8660 },
|
||||
{ @"∀", 8704 },
|
||||
{ @"∂", 8706 },
|
||||
{ @"∃", 8707 },
|
||||
{ @"∅", 8709 },
|
||||
{ @"∇", 8711 },
|
||||
{ @"∈", 8712 },
|
||||
{ @"∉", 8713 },
|
||||
{ @"∋", 8715 },
|
||||
{ @"∏", 8719 },
|
||||
{ @"∑", 8721 },
|
||||
{ @"−", 8722 },
|
||||
{ @"∗", 8727 },
|
||||
{ @"√", 8730 },
|
||||
{ @"∝", 8733 },
|
||||
{ @"∞", 8734 },
|
||||
{ @"∠", 8736 },
|
||||
{ @"∧", 8743 },
|
||||
{ @"∨", 8744 },
|
||||
{ @"∩", 8745 },
|
||||
{ @"∪", 8746 },
|
||||
{ @"∫", 8747 },
|
||||
{ @"∴", 8756 },
|
||||
{ @"∼", 8764 },
|
||||
{ @"≅", 8773 },
|
||||
{ @"≈", 8776 },
|
||||
{ @"≠", 8800 },
|
||||
{ @"≡", 8801 },
|
||||
{ @"≤", 8804 },
|
||||
{ @"≥", 8805 },
|
||||
{ @"⊂", 8834 },
|
||||
{ @"⊃", 8835 },
|
||||
{ @"⊄", 8836 },
|
||||
{ @"⊆", 8838 },
|
||||
{ @"⊇", 8839 },
|
||||
{ @"⊕", 8853 },
|
||||
{ @"⊗", 8855 },
|
||||
{ @"⊥", 8869 },
|
||||
{ @"⋅", 8901 },
|
||||
{ @"⌈", 8968 },
|
||||
{ @"⌉", 8969 },
|
||||
{ @"⌊", 8970 },
|
||||
{ @"⌋", 8971 },
|
||||
{ @"⟨", 9001 },
|
||||
{ @"⟩", 9002 },
|
||||
{ @"◊", 9674 },
|
||||
{ @"♠", 9824 },
|
||||
{ @"♣", 9827 },
|
||||
{ @"♥", 9829 },
|
||||
{ @"♦", 9830 }
|
||||
};
|
||||
|
||||
// Taken from http://www.w3.org/TR/xhtml1/dtds.html#a_dtd_Special_characters
|
||||
// This is table A.2.2 Special Characters
|
||||
static HTMLEscapeMap gUnicodeHTMLEscapeMap[] = {
|
||||
// C0 Controls and Basic Latin
|
||||
{ @""", 34 },
|
||||
{ @"&", 38 },
|
||||
{ @"'", 39 },
|
||||
{ @"<", 60 },
|
||||
{ @">", 62 },
|
||||
|
||||
// Latin Extended-A
|
||||
{ @"Œ", 338 },
|
||||
{ @"œ", 339 },
|
||||
{ @"Š", 352 },
|
||||
{ @"š", 353 },
|
||||
{ @"Ÿ", 376 },
|
||||
|
||||
// Spacing Modifier Letters
|
||||
{ @"ˆ", 710 },
|
||||
{ @"˜", 732 },
|
||||
|
||||
// General Punctuation
|
||||
{ @" ", 8194 },
|
||||
{ @" ", 8195 },
|
||||
{ @" ", 8201 },
|
||||
{ @"‌", 8204 },
|
||||
{ @"‍", 8205 },
|
||||
{ @"‎", 8206 },
|
||||
{ @"‏", 8207 },
|
||||
{ @"–", 8211 },
|
||||
{ @"—", 8212 },
|
||||
{ @"‘", 8216 },
|
||||
{ @"’", 8217 },
|
||||
{ @"‚", 8218 },
|
||||
{ @"“", 8220 },
|
||||
{ @"”", 8221 },
|
||||
{ @"„", 8222 },
|
||||
{ @"†", 8224 },
|
||||
{ @"‡", 8225 },
|
||||
{ @"‰", 8240 },
|
||||
{ @"‹", 8249 },
|
||||
{ @"›", 8250 },
|
||||
{ @"€", 8364 },
|
||||
};
|
||||
|
||||
|
||||
// Utility function for Bsearching table above
|
||||
static int EscapeMapCompare(const void *ucharVoid, const void *mapVoid) {
|
||||
const unichar *uchar = (const unichar*)ucharVoid;
|
||||
const HTMLEscapeMap *map = (const HTMLEscapeMap*)mapVoid;
|
||||
int val;
|
||||
if (*uchar > map->uchar) {
|
||||
val = 1;
|
||||
} else if (*uchar < map->uchar) {
|
||||
val = -1;
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
@implementation NSString (GTMNSStringHTMLAdditions)
|
||||
|
||||
- (NSString *)gtm_stringByEscapingHTMLUsingTable:(HTMLEscapeMap*)table
|
||||
ofSize:(NSUInteger)size
|
||||
escapingUnicode:(BOOL)escapeUnicode {
|
||||
NSUInteger length = [self length];
|
||||
if (!length) {
|
||||
return self;
|
||||
}
|
||||
|
||||
NSMutableString *finalString = [NSMutableString string];
|
||||
NSMutableData *data2 = [NSMutableData dataWithCapacity:sizeof(unichar) * length];
|
||||
|
||||
// this block is common between GTMNSString+HTML and GTMNSString+XML but
|
||||
// it's so short that it isn't really worth trying to share.
|
||||
const unichar *buffer = CFStringGetCharactersPtr((CFStringRef)self);
|
||||
if (!buffer) {
|
||||
// We want this buffer to be autoreleased.
|
||||
NSMutableData *data = [NSMutableData dataWithLength:length * sizeof(UniChar)];
|
||||
if (!data) {
|
||||
// COV_NF_START - Memory fail case
|
||||
_GTMDevLog(@"couldn't alloc buffer");
|
||||
return nil;
|
||||
// COV_NF_END
|
||||
}
|
||||
[self getCharacters:[data mutableBytes]];
|
||||
buffer = [data bytes];
|
||||
}
|
||||
|
||||
if (!buffer || !data2) {
|
||||
// COV_NF_START
|
||||
_GTMDevLog(@"Unable to allocate buffer or data2");
|
||||
return nil;
|
||||
// COV_NF_END
|
||||
}
|
||||
|
||||
unichar *buffer2 = (unichar *)[data2 mutableBytes];
|
||||
|
||||
NSUInteger buffer2Length = 0;
|
||||
|
||||
for (NSUInteger i = 0; i < length; ++i) {
|
||||
HTMLEscapeMap *val = bsearch(&buffer[i], table,
|
||||
size / sizeof(HTMLEscapeMap),
|
||||
sizeof(HTMLEscapeMap), EscapeMapCompare);
|
||||
if (val || (escapeUnicode && buffer[i] > 127)) {
|
||||
if (buffer2Length) {
|
||||
CFStringAppendCharacters((CFMutableStringRef)finalString,
|
||||
buffer2,
|
||||
buffer2Length);
|
||||
buffer2Length = 0;
|
||||
}
|
||||
if (val) {
|
||||
[finalString appendString:val->escapeSequence];
|
||||
}
|
||||
else {
|
||||
_GTMDevAssert(escapeUnicode && buffer[i] > 127, @"Illegal Character");
|
||||
[finalString appendFormat:@"&#%d;", buffer[i]];
|
||||
}
|
||||
} else {
|
||||
buffer2[buffer2Length] = buffer[i];
|
||||
buffer2Length += 1;
|
||||
}
|
||||
}
|
||||
if (buffer2Length) {
|
||||
CFStringAppendCharacters((CFMutableStringRef)finalString,
|
||||
buffer2,
|
||||
buffer2Length);
|
||||
}
|
||||
return finalString;
|
||||
}
|
||||
|
||||
- (NSString *)gtm_stringByEscapingForHTML {
|
||||
return [self gtm_stringByEscapingHTMLUsingTable:gUnicodeHTMLEscapeMap
|
||||
ofSize:sizeof(gUnicodeHTMLEscapeMap)
|
||||
escapingUnicode:NO];
|
||||
} // gtm_stringByEscapingHTML
|
||||
|
||||
- (NSString *)gtm_stringByEscapingForAsciiHTML {
|
||||
return [self gtm_stringByEscapingHTMLUsingTable:gAsciiHTMLEscapeMap
|
||||
ofSize:sizeof(gAsciiHTMLEscapeMap)
|
||||
escapingUnicode:YES];
|
||||
} // gtm_stringByEscapingAsciiHTML
|
||||
|
||||
- (NSString *)gtm_stringByUnescapingFromHTML {
|
||||
NSRange range = NSMakeRange(0, [self length]);
|
||||
NSRange subrange = [self rangeOfString:@"&" options:NSBackwardsSearch range:range];
|
||||
|
||||
// if no ampersands, we've got a quick way out
|
||||
if (subrange.length == 0) return self;
|
||||
NSMutableString *finalString = [NSMutableString stringWithString:self];
|
||||
do {
|
||||
NSRange semiColonRange = NSMakeRange(subrange.location, NSMaxRange(range) - subrange.location);
|
||||
semiColonRange = [self rangeOfString:@";" options:0 range:semiColonRange];
|
||||
range = NSMakeRange(0, subrange.location);
|
||||
// if we don't find a semicolon in the range, we don't have a sequence
|
||||
if (semiColonRange.location == NSNotFound) {
|
||||
continue;
|
||||
}
|
||||
NSRange escapeRange = NSMakeRange(subrange.location, semiColonRange.location - subrange.location + 1);
|
||||
NSString *escapeString = [self substringWithRange:escapeRange];
|
||||
NSUInteger length = [escapeString length];
|
||||
// a squence must be longer than 3 (<) and less than 11 (ϑ)
|
||||
if (length > 3 && length < 11) {
|
||||
if ([escapeString characterAtIndex:1] == '#') {
|
||||
unichar char2 = [escapeString characterAtIndex:2];
|
||||
if (char2 == 'x' || char2 == 'X') {
|
||||
// Hex escape squences £
|
||||
NSString *hexSequence = [escapeString substringWithRange:NSMakeRange(3, length - 4)];
|
||||
NSScanner *scanner = [NSScanner scannerWithString:hexSequence];
|
||||
unsigned value;
|
||||
if ([scanner scanHexInt:&value] &&
|
||||
value < USHRT_MAX &&
|
||||
value > 0
|
||||
&& [scanner scanLocation] == length - 4) {
|
||||
unichar uchar = value;
|
||||
NSString *charString = [NSString stringWithCharacters:&uchar length:1];
|
||||
[finalString replaceCharactersInRange:escapeRange withString:charString];
|
||||
}
|
||||
|
||||
} else {
|
||||
// Decimal Sequences {
|
||||
NSString *numberSequence = [escapeString substringWithRange:NSMakeRange(2, length - 3)];
|
||||
NSScanner *scanner = [NSScanner scannerWithString:numberSequence];
|
||||
int value;
|
||||
if ([scanner scanInt:&value] &&
|
||||
value < USHRT_MAX &&
|
||||
value > 0
|
||||
&& [scanner scanLocation] == length - 3) {
|
||||
unichar uchar = value;
|
||||
NSString *charString = [NSString stringWithCharacters:&uchar length:1];
|
||||
[finalString replaceCharactersInRange:escapeRange withString:charString];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// "standard" sequences
|
||||
for (unsigned i = 0; i < sizeof(gAsciiHTMLEscapeMap) / sizeof(HTMLEscapeMap); ++i) {
|
||||
if ([escapeString isEqualToString:gAsciiHTMLEscapeMap[i].escapeSequence]) {
|
||||
[finalString replaceCharactersInRange:escapeRange withString:[NSString stringWithCharacters:&gAsciiHTMLEscapeMap[i].uchar length:1]];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ((subrange = [self rangeOfString:@"&" options:NSBackwardsSearch range:range]).length != 0);
|
||||
return finalString;
|
||||
} // gtm_stringByUnescapingHTML
|
||||
|
||||
|
||||
|
||||
@end
|
46
media/iphone/NSString+HTML.h
Normal file
46
media/iphone/NSString+HTML.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// NSString+HTML.h
|
||||
// MWFeedParser
|
||||
//
|
||||
// Copyright (c) 2010 Michael Waterfall
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// 1. The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// 2. This Software cannot be used to archive or collect data such as (but not
|
||||
// limited to) that of events, news, experiences and activities, for the
|
||||
// purpose of any concept relating to diary/journal keeping.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
// Dependant upon GTMNSString+HTML
|
||||
|
||||
@interface NSString (HTML)
|
||||
|
||||
// Instance Methods
|
||||
- (NSString *)stringByConvertingHTMLToPlainText;
|
||||
- (NSString *)stringByDecodingHTMLEntities;
|
||||
- (NSString *)stringByEncodingHTMLEntities;
|
||||
- (NSString *)stringWithNewLinesAsBRs;
|
||||
- (NSString *)stringByRemovingNewLinesAndWhitespace;
|
||||
|
||||
// DEPRECIATED - Please use NSString stringByConvertingHTMLToPlainText
|
||||
- (NSString *)stringByStrippingTags;
|
||||
|
||||
@end
|
336
media/iphone/NSString+HTML.m
Normal file
336
media/iphone/NSString+HTML.m
Normal file
|
@ -0,0 +1,336 @@
|
|||
//
|
||||
// NSString+HTML.m
|
||||
// MWFeedParser
|
||||
//
|
||||
// Copyright (c) 2010 Michael Waterfall
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// 1. The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// 2. This Software cannot be used to archive or collect data such as (but not
|
||||
// limited to) that of events, news, experiences and activities, for the
|
||||
// purpose of any concept relating to diary/journal keeping.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
#import "NSString+HTML.h"
|
||||
#import "GTMNString+HTML.h"
|
||||
|
||||
@implementation NSString (HTML)
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Class Methods
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Instance Methods
|
||||
|
||||
// Strip HTML tags
|
||||
- (NSString *)stringByConvertingHTMLToPlainText {
|
||||
|
||||
// Pool
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
// Character sets
|
||||
NSCharacterSet *stopCharacters = [NSCharacterSet characterSetWithCharactersInString:[NSString stringWithFormat:@"< \t\n\r%C%C%C%C", 0x0085, 0x000C, 0x2028, 0x2029]];
|
||||
NSCharacterSet *newLineAndWhitespaceCharacters = [NSCharacterSet characterSetWithCharactersInString:[NSString stringWithFormat:@" \t\n\r%C%C%C%C", 0x0085, 0x000C, 0x2028, 0x2029]];
|
||||
NSCharacterSet *tagNameCharacters = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"]; /**/
|
||||
|
||||
// Scan and find all tags
|
||||
NSMutableString *result = [[NSMutableString alloc] initWithCapacity:self.length];
|
||||
NSScanner *scanner = [[NSScanner alloc] initWithString:self];
|
||||
[scanner setCharactersToBeSkipped:nil];
|
||||
[scanner setCaseSensitive:YES];
|
||||
NSString *str = nil, *tagName = nil;
|
||||
BOOL dontReplaceTagWithSpace = NO;
|
||||
do {
|
||||
|
||||
// Scan up to the start of a tag or whitespace
|
||||
if ([scanner scanUpToCharactersFromSet:stopCharacters intoString:&str]) {
|
||||
[result appendString:str];
|
||||
str = nil; // reset
|
||||
}
|
||||
|
||||
// Check if we've stopped at a tag/comment or whitespace
|
||||
if ([scanner scanString:@"<" intoString:NULL]) {
|
||||
|
||||
// Stopped at a comment or tag
|
||||
if ([scanner scanString:@"!--" intoString:NULL]) {
|
||||
|
||||
// Comment
|
||||
[scanner scanUpToString:@"-->" intoString:NULL];
|
||||
[scanner scanString:@"-->" intoString:NULL];
|
||||
|
||||
} else {
|
||||
|
||||
// Tag - remove and replace with space unless it's
|
||||
// a closing inline tag then dont replace with a space
|
||||
if ([scanner scanString:@"/" intoString:NULL]) {
|
||||
|
||||
// Closing tag - replace with space unless it's inline
|
||||
tagName = nil; dontReplaceTagWithSpace = NO;
|
||||
if ([scanner scanCharactersFromSet:tagNameCharacters intoString:&tagName]) {
|
||||
tagName = [tagName lowercaseString];
|
||||
dontReplaceTagWithSpace = ([tagName isEqualToString:@"a"] ||
|
||||
[tagName isEqualToString:@"b"] ||
|
||||
[tagName isEqualToString:@"i"] ||
|
||||
[tagName isEqualToString:@"q"] ||
|
||||
[tagName isEqualToString:@"span"] ||
|
||||
[tagName isEqualToString:@"em"] ||
|
||||
[tagName isEqualToString:@"strong"] ||
|
||||
[tagName isEqualToString:@"cite"] ||
|
||||
[tagName isEqualToString:@"abbr"] ||
|
||||
[tagName isEqualToString:@"acronym"] ||
|
||||
[tagName isEqualToString:@"label"]);
|
||||
}
|
||||
|
||||
// Replace tag with string unless it was an inline
|
||||
if (!dontReplaceTagWithSpace && result.length > 0 && ![scanner isAtEnd]) [result appendString:@" "];
|
||||
|
||||
}
|
||||
|
||||
// Scan past tag
|
||||
[scanner scanUpToString:@">" intoString:NULL];
|
||||
[scanner scanString:@">" intoString:NULL];
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Stopped at whitespace - replace all whitespace and newlines with a space
|
||||
if ([scanner scanCharactersFromSet:newLineAndWhitespaceCharacters intoString:NULL]) {
|
||||
if (result.length > 0 && ![scanner isAtEnd]) [result appendString:@" "]; // Dont append space to beginning or end of result
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} while (![scanner isAtEnd]);
|
||||
|
||||
// Cleanup
|
||||
[scanner release];
|
||||
|
||||
// Decode HTML entities and return
|
||||
NSString *retString = [[result stringByDecodingHTMLEntities] retain];
|
||||
[result release];
|
||||
|
||||
// Drain
|
||||
[pool drain];
|
||||
|
||||
// Return
|
||||
return [retString autorelease];
|
||||
|
||||
}
|
||||
|
||||
// Decode all HTML entities using GTM
|
||||
- (NSString *)stringByDecodingHTMLEntities {
|
||||
// gtm_stringByUnescapingFromHTML can return self so create new string ;)
|
||||
return [NSString stringWithString:[self gtm_stringByUnescapingFromHTML]];
|
||||
}
|
||||
|
||||
// Encode all HTML entities using GTM
|
||||
- (NSString *)stringByEncodingHTMLEntities {
|
||||
// gtm_stringByUnescapingFromHTML can return self so create new string ;)
|
||||
return [NSString stringWithString:[self gtm_stringByEscapingForAsciiHTML]];
|
||||
}
|
||||
|
||||
// Replace newlines with <br /> tags
|
||||
- (NSString *)stringWithNewLinesAsBRs {
|
||||
|
||||
// Pool
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
// Strange New lines:
|
||||
// Next Line, U+0085
|
||||
// Form Feed, U+000C
|
||||
// Line Separator, U+2028
|
||||
// Paragraph Separator, U+2029
|
||||
|
||||
// Scanner
|
||||
NSScanner *scanner = [[NSScanner alloc] initWithString:self];
|
||||
[scanner setCharactersToBeSkipped:nil];
|
||||
NSMutableString *result = [[NSMutableString alloc] init];
|
||||
NSString *temp;
|
||||
NSCharacterSet *newLineCharacters = [NSCharacterSet characterSetWithCharactersInString:
|
||||
[NSString stringWithFormat:@"\n\r%C%C%C%C", 0x0085, 0x000C, 0x2028, 0x2029]];
|
||||
// Scan
|
||||
do {
|
||||
|
||||
// Get non new line characters
|
||||
temp = nil;
|
||||
[scanner scanUpToCharactersFromSet:newLineCharacters intoString:&temp];
|
||||
if (temp) [result appendString:temp];
|
||||
temp = nil;
|
||||
|
||||
// Add <br /> s
|
||||
if ([scanner scanString:@"\r\n" intoString:nil]) {
|
||||
|
||||
// Combine \r\n into just 1 <br />
|
||||
[result appendString:@"<br />"];
|
||||
|
||||
} else if ([scanner scanCharactersFromSet:newLineCharacters intoString:&temp]) {
|
||||
|
||||
// Scan other new line characters and add <br /> s
|
||||
if (temp) {
|
||||
for (int i = 0; i < temp.length; i++) {
|
||||
[result appendString:@"<br />"];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} while (![scanner isAtEnd]);
|
||||
|
||||
// Cleanup & return
|
||||
[scanner release];
|
||||
NSString *retString = [[NSString stringWithString:result] retain];
|
||||
[result release];
|
||||
|
||||
// Drain
|
||||
[pool drain];
|
||||
|
||||
// Return
|
||||
return [retString autorelease];
|
||||
|
||||
}
|
||||
|
||||
// Remove newlines and white space from strong
|
||||
- (NSString *)stringByRemovingNewLinesAndWhitespace {
|
||||
|
||||
// Pool
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
// Strange New lines:
|
||||
// Next Line, U+0085
|
||||
// Form Feed, U+000C
|
||||
// Line Separator, U+2028
|
||||
// Paragraph Separator, U+2029
|
||||
|
||||
// Scanner
|
||||
NSScanner *scanner = [[NSScanner alloc] initWithString:self];
|
||||
[scanner setCharactersToBeSkipped:nil];
|
||||
NSMutableString *result = [[NSMutableString alloc] init];
|
||||
NSString *temp;
|
||||
NSCharacterSet *newLineAndWhitespaceCharacters = [NSCharacterSet characterSetWithCharactersInString:
|
||||
[NSString stringWithFormat:@" \t\n\r%C%C%C%C", 0x0085, 0x000C, 0x2028, 0x2029]];
|
||||
// Scan
|
||||
while (![scanner isAtEnd]) {
|
||||
|
||||
// Get non new line or whitespace characters
|
||||
temp = nil;
|
||||
[scanner scanUpToCharactersFromSet:newLineAndWhitespaceCharacters intoString:&temp];
|
||||
if (temp) [result appendString:temp];
|
||||
|
||||
// Replace with a space
|
||||
if ([scanner scanCharactersFromSet:newLineAndWhitespaceCharacters intoString:NULL]) {
|
||||
if (result.length > 0 && ![scanner isAtEnd]) // Dont append space to beginning or end of result
|
||||
[result appendString:@" "];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
[scanner release];
|
||||
|
||||
// Return
|
||||
NSString *retString = [[NSString stringWithString:result] retain];
|
||||
[result release];
|
||||
|
||||
// Drain
|
||||
[pool drain];
|
||||
|
||||
// Return
|
||||
return [retString autorelease];
|
||||
|
||||
}
|
||||
|
||||
// Strip HTML tags
|
||||
// DEPRECIATED - Please use NSString stringByConvertingHTMLToPlainText
|
||||
- (NSString *)stringByStrippingTags {
|
||||
|
||||
// Pool
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
// Find first & and short-cut if we can
|
||||
NSUInteger ampIndex = [self rangeOfString:@"<" options:NSLiteralSearch].location;
|
||||
if (ampIndex == NSNotFound) {
|
||||
return [NSString stringWithString:self]; // return copy of string as no tags found
|
||||
}
|
||||
|
||||
// Scan and find all tags
|
||||
NSScanner *scanner = [NSScanner scannerWithString:self];
|
||||
[scanner setCharactersToBeSkipped:nil];
|
||||
NSMutableSet *tags = [[NSMutableSet alloc] init];
|
||||
NSString *tag;
|
||||
do {
|
||||
|
||||
// Scan up to <
|
||||
tag = nil;
|
||||
[scanner scanUpToString:@"<" intoString:NULL];
|
||||
[scanner scanUpToString:@">" intoString:&tag];
|
||||
|
||||
// Add to set
|
||||
if (tag) {
|
||||
NSString *t = [[NSString alloc] initWithFormat:@"%@>", tag];
|
||||
[tags addObject:t];
|
||||
[t release];
|
||||
}
|
||||
|
||||
} while (![scanner isAtEnd]);
|
||||
|
||||
// Strings
|
||||
NSMutableString *result = [[NSMutableString alloc] initWithString:self];
|
||||
NSString *finalString;
|
||||
|
||||
// Replace tags
|
||||
NSString *replacement;
|
||||
for (NSString *t in tags) {
|
||||
|
||||
// Replace tag with space unless it's an inline element
|
||||
replacement = @" ";
|
||||
if ([t isEqualToString:@"<a>"] ||
|
||||
[t isEqualToString:@"</a>"] ||
|
||||
[t isEqualToString:@"<span>"] ||
|
||||
[t isEqualToString:@"</span>"] ||
|
||||
[t isEqualToString:@"<strong>"] ||
|
||||
[t isEqualToString:@"</strong>"] ||
|
||||
[t isEqualToString:@"<em>"] ||
|
||||
[t isEqualToString:@"</em>"]) {
|
||||
replacement = @"";
|
||||
}
|
||||
|
||||
// Replace
|
||||
[result replaceOccurrencesOfString:t
|
||||
withString:replacement
|
||||
options:NSLiteralSearch
|
||||
range:NSMakeRange(0, result.length)];
|
||||
}
|
||||
|
||||
// Remove multi-spaces and line breaks
|
||||
finalString = [[result stringByRemovingNewLinesAndWhitespace] retain];
|
||||
|
||||
// Cleanup
|
||||
[result release];
|
||||
[tags release];
|
||||
|
||||
// Drain
|
||||
[pool drain];
|
||||
|
||||
// Return
|
||||
return [finalString autorelease];
|
||||
|
||||
}
|
||||
|
||||
@end
|
|
@ -48,6 +48,8 @@
|
|||
78FC34FA11CA94900055C312 /* SBJsonBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 78FC34F211CA94900055C312 /* SBJsonBase.m */; };
|
||||
78FC34FB11CA94900055C312 /* SBJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 78FC34F411CA94900055C312 /* SBJsonParser.m */; };
|
||||
78FC34FC11CA94900055C312 /* SBJsonWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 78FC34F611CA94900055C312 /* SBJsonWriter.m */; };
|
||||
FF38679B13D88EEC00F8AB3A /* NSString+HTML.m in Sources */ = {isa = PBXBuildFile; fileRef = FF38679A13D88EEC00F8AB3A /* NSString+HTML.m */; };
|
||||
FF38679E13D8914A00F8AB3A /* GTMNString+HTML.m in Sources */ = {isa = PBXBuildFile; fileRef = FF38679D13D8914A00F8AB3A /* GTMNString+HTML.m */; };
|
||||
FFCE7AE813D49165009A98F6 /* FeedTableCell.m in Sources */ = {isa = PBXBuildFile; fileRef = FFCE7AE613D49165009A98F6 /* FeedTableCell.m */; };
|
||||
FFCE7AE913D49165009A98F6 /* FeedTableCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = FFCE7AE713D49165009A98F6 /* FeedTableCell.xib */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
@ -122,6 +124,11 @@
|
|||
78FC34F511CA94900055C312 /* SBJsonWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonWriter.h; sourceTree = "<group>"; };
|
||||
78FC34F611CA94900055C312 /* SBJsonWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonWriter.m; sourceTree = "<group>"; };
|
||||
8D1107310486CEB800E47090 /* NewsBlur-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "NewsBlur-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; };
|
||||
FF38679913D88EEC00F8AB3A /* NSString+HTML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+HTML.h"; sourceTree = "<group>"; };
|
||||
FF38679A13D88EEC00F8AB3A /* NSString+HTML.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+HTML.m"; sourceTree = "<group>"; };
|
||||
FF38679C13D8914A00F8AB3A /* GTMNString+HTML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GTMNString+HTML.h"; sourceTree = "<group>"; };
|
||||
FF38679D13D8914A00F8AB3A /* GTMNString+HTML.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GTMNString+HTML.m"; sourceTree = "<group>"; };
|
||||
FF38679F13D8916E00F8AB3A /* GTMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTMDefines.h; sourceTree = "<group>"; };
|
||||
FFCE7AE513D49165009A98F6 /* FeedTableCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FeedTableCell.h; path = ../NewsBlur.xcodeproj/FeedTableCell.h; sourceTree = "<group>"; };
|
||||
FFCE7AE613D49165009A98F6 /* FeedTableCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FeedTableCell.m; path = ../NewsBlur.xcodeproj/FeedTableCell.m; sourceTree = "<group>"; };
|
||||
FFCE7AE713D49165009A98F6 /* FeedTableCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = FeedTableCell.xib; path = ../NewsBlur.xcodeproj/FeedTableCell.xib; sourceTree = "<group>"; };
|
||||
|
@ -202,6 +209,11 @@
|
|||
children = (
|
||||
32CA4F630368D1EE00C91783 /* NewsBlur_Prefix.pch */,
|
||||
29B97316FDCFA39411CA2CEA /* main.m */,
|
||||
FF38679913D88EEC00F8AB3A /* NSString+HTML.h */,
|
||||
FF38679C13D8914A00F8AB3A /* GTMNString+HTML.h */,
|
||||
FF38679F13D8916E00F8AB3A /* GTMDefines.h */,
|
||||
FF38679D13D8914A00F8AB3A /* GTMNString+HTML.m */,
|
||||
FF38679A13D88EEC00F8AB3A /* NSString+HTML.m */,
|
||||
);
|
||||
name = "Other Sources";
|
||||
sourceTree = "<group>";
|
||||
|
@ -387,6 +399,8 @@
|
|||
78095E3D128EF32200230C8E /* Reachability.m in Sources */,
|
||||
78095EC9128F30B500230C8E /* OriginalStoryViewController.m in Sources */,
|
||||
FFCE7AE813D49165009A98F6 /* FeedTableCell.m in Sources */,
|
||||
FF38679B13D88EEC00F8AB3A /* NSString+HTML.m in Sources */,
|
||||
FF38679E13D8914A00F8AB3A /* GTMNString+HTML.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue