Skip to content

Commit

Permalink
Merge branch 'release-1.6.24'
Browse files Browse the repository at this point in the history
  • Loading branch information
odrobnik committed Aug 6, 2020
2 parents e9cc5bb + 5e192b2 commit 83e0462
Show file tree
Hide file tree
Showing 18 changed files with 200 additions and 74 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ - (DTAccessibilityElement *)accessibilityElementForTextInAttributedString:(NSAtt
element.accessibilityLabel = text;
element.localCoordinateAccessibilityFrame = [self frameForRuns:runs];

// We're trying to keep the accessibility frame behavior consistent with UIWebView, which seems to do a union of the rects for all the runs composing a single accessibility group,
// We're trying to keep the accessibility frame behavior consistent with web view, which seems to do a union of the rects for all the runs composing a single accessibility group,
// even if that spans across multiple lines. Set the local coordinate activation point to support multi-line links. A link that is at the end of one line and
// wraps to the beginning of the next would have a rect that's the size of both lines combined. The center of that rect would be outside the hit areas for either of the
// runs individually, so we set the accessibility activation point to be the origin of the first run.
Expand Down
7 changes: 5 additions & 2 deletions Core/Source/DTHTMLAttributedStringBuilder.m
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,11 @@ - (void)_registerTagStartHandlers
}

NSURL *link = [NSURL URLWithString:cleanString];
if (link == nil) {
link = [NSURL URLWithString:[cleanString stringByURLEncoding]];

if (link == nil)
{
cleanString = [cleanString stringByEncodingNonASCIICharacters];
link = [NSURL URLWithString:cleanString];
}

// deal with relative URL
Expand Down
6 changes: 3 additions & 3 deletions Core/Source/DTHTMLElement.m
Original file line number Diff line number Diff line change
Expand Up @@ -1572,15 +1572,15 @@ - (void)interpretAttributes

if ([directionStr isEqualToString:@"rtl"])
{
_paragraphStyle.baseWritingDirection = NSWritingDirectionRightToLeft;
_paragraphStyle.baseWritingDirection = kCTWritingDirectionRightToLeft;
}
else if ([directionStr isEqualToString:@"ltr"])
{
_paragraphStyle.baseWritingDirection = NSWritingDirectionLeftToRight;
_paragraphStyle.baseWritingDirection = kCTWritingDirectionLeftToRight;
}
else if ([directionStr isEqualToString:@"auto"])
{
_paragraphStyle.baseWritingDirection = NSWritingDirectionNatural; // that's also default
_paragraphStyle.baseWritingDirection = kCTWritingDirectionNatural; // that's also default
}
else
{
Expand Down
7 changes: 7 additions & 0 deletions Core/Source/NSCharacterSet+HTML.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,11 @@
*/
+ (NSCharacterSet *)cssLengthUnitCharacterSet;

/**
Characterset of ASCII Characters
@returns An NSCharacterSet
*/

+ (NSCharacterSet *)ASCIICharacterSet;

@end
15 changes: 14 additions & 1 deletion Core/Source/NSCharacterSet+HTML.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
static NSCharacterSet *_cssStyleAttributeNameCharacterSet = nil;
static NSCharacterSet *_cssLengthValueCharacterSet = nil;
static NSCharacterSet *_cssLengthUnitCharacterSet = nil;

static NSCharacterSet *_asciiCharacterSet = nil;


@implementation NSCharacterSet (HTML)
Expand Down Expand Up @@ -136,4 +136,17 @@ + (NSCharacterSet *)cssLengthUnitCharacterSet
return _cssLengthUnitCharacterSet;
}

+ (NSCharacterSet *)ASCIICharacterSet
{
static dispatch_once_t predicate;

dispatch_once(&predicate, ^{
NSMutableCharacterSet *tmpSet = [NSMutableCharacterSet new];
[tmpSet addCharactersInRange:NSMakeRange(32, 96)];
_asciiCharacterSet = [tmpSet copy];
});

return _asciiCharacterSet;
}

@end
2 changes: 1 addition & 1 deletion Core/Source/NSScanner+HTML.m
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ - (BOOL)scanCSSAttribute:(NSString * __autoreleasing*)name value:(id __autorelea
NSMutableArray *results = [NSMutableArray array];
BOOL nextIterationAddsNewEntry = YES;

while (![self isAtEnd] && ![self scanString:@";" intoString:NULL])
while (![self isAtEnd] && ![self scanString:@";" intoString:NULL] && ![self scanString:@"'';" intoString:NULL] && ![self scanString:@"\"\";" intoString:NULL])
{
// skip whitespace
[self scanCharactersFromSet:whiteCharacterSet intoString:NULL];
Expand Down
5 changes: 5 additions & 0 deletions Core/Source/NSString+HTML.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,9 @@
*/
- (NSString *)stringByAddingAppleConvertedSpace;

/**
Percent-encodes all characters outside the normal ASCII range
*/
- (NSString *)stringByEncodingNonASCIICharacters;

@end
10 changes: 10 additions & 0 deletions Core/Source/NSString+HTML.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#import "NSString+HTML.h"
#import "NSCharacterSet+HTML.h"
#import "DTCoreTextConstants.h"
#import <DTFoundation/NSString+DTURLEncoding.h>

static NSDictionary *entityLookup = nil;
static NSDictionary *entityReverseLookup = nil;
Expand Down Expand Up @@ -798,4 +799,13 @@ - (NSString *)stringByAddingAppleConvertedSpace
return output;
}

- (NSString *)stringByEncodingNonASCIICharacters
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED < __IPHONE_7_0
return [self stringByURLEncoding];
#else
return [self stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet ASCIICharacterSet]];
#endif
}

@end
2 changes: 1 addition & 1 deletion DTCoreText.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |spec|
spec.name = 'DTCoreText'
spec.version = '1.6.23'
spec.version = '1.6.24'
spec.platforms = {:ios => '4.3', :tvos => '9.0' }
spec.license = 'BSD'
spec.source = { :git => 'https://github.com/Cocoanetics/DTCoreText.git', :tag => spec.version.to_s }
Expand Down
10 changes: 7 additions & 3 deletions DTCoreText.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@
A76E5B4912DD9AF500711782 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A76E5B4812DD9AF500711782 /* QuartzCore.framework */; };
A776DBE81716A8EE00E71F36 /* NSStringParagraphTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A776DBE71716A8EE00E71F36 /* NSStringParagraphTest.m */; };
A77A3E421779BF04000B290B /* NSMutableAttributedStringHTMLTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A77A3E411779BF03000B290B /* NSMutableAttributedStringHTMLTest.m */; };
A786FBAB247BFC1D00890B3D /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A786FB91247BFC1D00890B3D /* WebKit.framework */; };
A788CA3A14863EF100E1AFD9 /* Alignment.html in Resources */ = {isa = PBXBuildFile; fileRef = A788CA1B14863EF100E1AFD9 /* Alignment.html */; };
A788CA3B14863EF100E1AFD9 /* APOD.html in Resources */ = {isa = PBXBuildFile; fileRef = A788CA1C14863EF100E1AFD9 /* APOD.html */; };
A788CA3C14863EF100E1AFD9 /* ArabicTest.html in Resources */ = {isa = PBXBuildFile; fileRef = A788CA1D14863EF100E1AFD9 /* ArabicTest.html */; };
Expand Down Expand Up @@ -882,6 +883,7 @@
A77A3E411779BF03000B290B /* NSMutableAttributedStringHTMLTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSMutableAttributedStringHTMLTest.m; sourceTree = "<group>"; };
A783CE6717D11D0100C84C28 /* CSSOOMCrash.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = CSSOOMCrash.plist; sourceTree = "<group>"; };
A785701C17FAA69D0080AB0A /* DTFoundation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = DTFoundation.xcodeproj; path = DTFoundation/DTFoundation.xcodeproj; sourceTree = "<group>"; };
A786FB91247BFC1D00890B3D /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.5.sdk/System/Library/Frameworks/WebKit.framework; sourceTree = DEVELOPER_DIR; };
A788C91014863E8700E1AFD9 /* DTAttributedTextCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTAttributedTextCell.h; sourceTree = "<group>"; };
A788C91114863E8700E1AFD9 /* DTAttributedTextCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = DTAttributedTextCell.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
A788C91214863E8700E1AFD9 /* DTAttributedTextContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DTAttributedTextContentView.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1082,6 +1084,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A786FBAB247BFC1D00890B3D /* WebKit.framework in Frameworks */,
A7949A0014C6256B00A8CCDE /* libxml2.dylib in Frameworks */,
A75C6C72141798CE00AEE350 /* MobileCoreServices.framework in Frameworks */,
A7D29D661CB68D470068F043 /* DTCoreText.framework in Frameworks */,
Expand Down Expand Up @@ -1194,6 +1197,7 @@
29B97323FDCFA39411CA2CEA /* Frameworks */ = {
isa = PBXGroup;
children = (
A786FB91247BFC1D00890B3D /* WebKit.framework */,
A74A7AAC1B617250004163BE /* QuartzCore.framework */,
A74A7AAA1B617227004163BE /* CoreGraphics.framework */,
A74A7AA81B617222004163BE /* UIKit.framework */,
Expand Down Expand Up @@ -3258,7 +3262,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 1.6.23;
CURRENT_PROJECT_VERSION = 1.6.24;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
GCC_C_LANGUAGE_STANDARD = c99;
Expand Down Expand Up @@ -3400,7 +3404,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 1.6.23;
CURRENT_PROJECT_VERSION = 1.6.24;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
Expand Down Expand Up @@ -3456,7 +3460,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CURRENT_PROJECT_VERSION = 1.6.23;
CURRENT_PROJECT_VERSION = 1.6.24;
ENABLE_STRICT_OBJC_MSGSEND = YES;
FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks";
GCC_C_LANGUAGE_STANDARD = c99;
Expand Down
4 changes: 2 additions & 2 deletions Demo/Resources/README.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<h2>NSAttributedString HTML Additions</h2>
<h3>Introduction</h3>
<p>This project aims to duplicate the methods <u>present on Mac OSX</u> which allow creation of <font face="Courier" color="blue">NSAttributedString</font> from HTML code.
This is useful for drawing simple rich text - like this document - without having to use a UIWebView.</p>
This is useful for drawing simple rich text - like this document - without having to use a web view.</p>
<p><img src="Oliver.jpg" width="100" height="100"></p>
<p style="color:orange;"><i>Hi! I'm Oliver and I appreciate your help!</i></p>
<h3>Features</h3>
Expand Down Expand Up @@ -30,4 +30,4 @@ <h3>Please Help!</h3>
<p>If you find brief test cases where the created <font face="Courier" color="blue">NSAttributedString</font> differs from the version on OSX please send them to us!</p>
<p>Also there are many small things that you could help this project with. You can either implement these yourself or sponsor their development.</p>
<p>Follow <a href="http://twitter.com/cocoanetics">@cocoanetics</a> on Twitter</p>
<p>This code is covered by a BSD License. &copy; 2011 Oliver Drobnik</p>
<p>This code is covered by a BSD License. &copy; 2011 Oliver Drobnik</p>
46 changes: 42 additions & 4 deletions Demo/Source/DemoTextViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,14 @@ - (void)linkPushed:(DTLinkButton *)button

if ([[UIApplication sharedApplication] canOpenURL:[URL absoluteURL]])
{
[[UIApplication sharedApplication] openURL:[URL absoluteURL]];
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:[URL absoluteURL] options:@{} completionHandler:nil];
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[[UIApplication sharedApplication] openURL:[URL absoluteURL]];
#pragma clang diagnostic pop
}
}
else
{
Expand All @@ -648,11 +655,22 @@ - (void)linkPushed:(DTLinkButton *)button
}
}

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
#pragma clang diagnostic pop
{
if (buttonIndex != actionSheet.cancelButtonIndex)
{
[[UIApplication sharedApplication] openURL:[self.lastActionLink absoluteURL]];
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:[self.lastActionLink absoluteURL] options:@{} completionHandler:nil];
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[[UIApplication sharedApplication] openURL:[self.lastActionLink absoluteURL]];
#pragma clang diagnostic pop
}
}
}

Expand All @@ -666,8 +684,28 @@ - (void)linkLongPressed:(UILongPressGestureRecognizer *)gesture

if ([[UIApplication sharedApplication] canOpenURL:[button.URL absoluteURL]])
{
UIActionSheet *action = [[UIActionSheet alloc] initWithTitle:[[button.URL absoluteURL] description] delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Open in Safari", nil];
[action showFromRect:button.frame inView:button.superview animated:YES];
if (@available(iOS 8.0, *)) {
UIAlertController *ac = [UIAlertController alertControllerWithTitle:[[button.URL absoluteURL] description]
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
[ac addAction:[UIAlertAction actionWithTitle:@"Open in Safari"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * _Nonnull action) {
[[UIApplication sharedApplication] openURL:[self.lastActionLink absoluteURL] options:@{} completionHandler:nil];
}]];

[ac addAction:[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:nil]];

[self presentViewController:ac animated:YES completion:nil];
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
UIActionSheet *action = [[UIActionSheet alloc] initWithTitle:[[button.URL absoluteURL] description] delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Open in Safari", nil];
[action showFromRect:button.frame inView:button.superview animated:YES];
#pragma clang diagnostic pop
}
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions Demo/Source/DemoWebVideoView.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

#import <DTFoundation/DTWeakSupport.h>
#import <WebKit/WebKit.h>

@class DemoWebVideoView;
@class DTTextAttachment;
Expand All @@ -33,11 +34,11 @@
/**
The class represents a custom subview for use in <DTAttributedTextContentView> to represent an embedded video.
Embedded videos work by loading the video URL in a UIWebView which iOS then replaces with the built-in media player view. The URL of the embed script depends on the service and needs to be added to the webView:shouldStartLoadWithRequest:navigationType:. You want to allow the URL for the embed script, but disallow all other requests which for example occur if a user taps on the YouTube logo. If you were to allow this type of navigation then the YouTube website would be loaded in the video view. For these scenarios there is the videoView:shouldOpenExternalURL: method in DemoWebVideoViewDelegate. If you respond with `YES` (which is default if the method is not implemented) then the URL will be opened in Safari.
Embedded videos work by loading the video URL in a web view which iOS then replaces with the built-in media player view. The URL of the embed script depends on the service and needs to be added to the webView:shouldStartLoadWithRequest:navigationType:. You want to allow the URL for the embed script, but disallow all other requests which for example occur if a user taps on the YouTube logo. If you were to allow this type of navigation then the YouTube website would be loaded in the video view. For these scenarios there is the videoView:shouldOpenExternalURL: method in DemoWebVideoViewDelegate. If you respond with `YES` (which is default if the method is not implemented) then the URL will be opened in Safari.
To add additional video services please add them in the mentioned location and submit a pull request for the addition.
*/
@interface DemoWebVideoView : UIView <UIWebViewDelegate>
@interface DemoWebVideoView : UIView <WKNavigationDelegate>

/**
The delegate of the video view
Expand Down
36 changes: 21 additions & 15 deletions Demo/Source/DemoWebVideoView.m
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ @implementation DemoWebVideoView

DT_WEAK_VARIABLE id <DemoWebVideoViewDelegate> _delegate;

UIWebView *_webView;
WKWebView *_webView;
}

- (id)initWithFrame:(CGRect)frame
Expand All @@ -32,25 +32,20 @@ - (id)initWithFrame:(CGRect)frame
{
self.userInteractionEnabled = YES;

_webView = [[UIWebView alloc] initWithFrame:self.bounds];
_webView = [[WKWebView alloc] initWithFrame:self.bounds];
_webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:_webView];

[self disableScrolling];

_webView.delegate = self;

if ([_webView respondsToSelector:@selector(setAllowsInlineMediaPlayback:)])
{
_webView.allowsInlineMediaPlayback = YES;
}
_webView.navigationDelegate = self;
}
return self;
}

- (void)dealloc
{
_webView.delegate = nil;
_webView.navigationDelegate = nil;

}

Expand All @@ -72,20 +67,24 @@ - (void)disableScrolling
}
}

#pragma mark UIWebViewDelegate
#pragma mark WKWebViewDelegate

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
NSURLRequest *request = navigationAction.request;

// allow the embed request for YouTube
if (NSNotFound != [[[request URL] absoluteString] rangeOfString:@"www.youtube.com/embed/"].location)
{
return YES;
decisionHandler(WKNavigationActionPolicyAllow);
return;
}

// allow the embed request for DailyMotion Cloud
if (NSNotFound != [[[request URL] absoluteString] rangeOfString:@"api.dmcloud.net/player/embed/"].location)
{
return YES;
decisionHandler(WKNavigationActionPolicyAllow);
return;
}

BOOL shouldOpenExternalURL = YES;
Expand All @@ -98,11 +97,18 @@ - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)
#if !defined(DT_APP_EXTENSIONS)
if (shouldOpenExternalURL)
{
[[UIApplication sharedApplication] openURL:[request URL]];
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:[request URL] options:@{} completionHandler:nil];
} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
[[UIApplication sharedApplication] openURL:[request URL]];
#pragma clang diagnostic pop
}
}
#endif

return NO;
decisionHandler(WKNavigationActionPolicyCancel);
}


Expand Down
2 changes: 1 addition & 1 deletion Readme.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The project covers two broad areas:
1. **Layouting** - Interfacing with CoreText, generating attributed strings from HTML code
2. **User Interface** - UI-related classes render these objects, specifically `DTAttributedTextView`, `DTAttributedLabel` and `DTAttributedTextCell`.

This is useful for drawing simple rich text like any HTML document without having to use a `UIWebView`. For text selection and highlighting (as you might need for an Editor or Reader) there is the commercial **DTRichTextEditor** component which can be purchased in the [Cocoanetics Parts Store](http://www.cocoanetics.com/parts/dtrichtexteditor/).
This is useful for drawing simple rich text like any HTML document without having to use a web view. For text selection and highlighting (as you might need for an Editor or Reader) there is the commercial **DTRichTextEditor** component which can be purchased in the [Cocoanetics Parts Store](http://www.cocoanetics.com/parts/dtrichtexteditor/).

Documentation
-------------
Expand Down
Loading

0 comments on commit 83e0462

Please sign in to comment.