Skip to content

Commit

Permalink
Merge branch 'release-1.6.6'
Browse files Browse the repository at this point in the history
  • Loading branch information
odrobnik committed Aug 30, 2013
2 parents 39ae9a6 + 7d6eee4 commit f3b8c52
Show file tree
Hide file tree
Showing 11 changed files with 373 additions and 76 deletions.
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
language: objective-c

script: Travis-CI/script.sh
67 changes: 38 additions & 29 deletions Core/Source/DTCSSStylesheet.m
Original file line number Diff line number Diff line change
Expand Up @@ -677,34 +677,34 @@ - (NSDictionary *)mergedStyleDictionaryForElement:(DTHTMLElement *)element match

// Cascaded selectors with more than one part are sorted by specificity
NSMutableArray *matchingCascadingSelectors = [self matchingComplexCascadingSelectorsForElement:element];
NSArray *sortedCascadingSelectors = [matchingCascadingSelectors sortedArrayUsingComparator:^NSComparisonResult(NSString *selector1, NSString *selector2)
{
NSInteger weightForSelector1 = [_orderedSelectorWeights[selector1] integerValue];
NSInteger weightForSelector2 = [_orderedSelectorWeights[selector2] integerValue];

if (weightForSelector1 == weightForSelector2)
{
weightForSelector1 += [_orderedSelectors indexOfObject:selector1];
weightForSelector2 += [_orderedSelectors indexOfObject:selector2];
}

if (weightForSelector1 > weightForSelector2)
{
return (NSComparisonResult)NSOrderedDescending;
}

if (weightForSelector1 < weightForSelector2)
{
return (NSComparisonResult)NSOrderedAscending;
}

return (NSComparisonResult)NSOrderedSame;
}];
[matchingCascadingSelectors sortUsingComparator:^NSComparisonResult(NSString *selector1, NSString *selector2)
{
NSInteger weightForSelector1 = [_orderedSelectorWeights[selector1] integerValue];
NSInteger weightForSelector2 = [_orderedSelectorWeights[selector2] integerValue];
if (weightForSelector1 == weightForSelector2)
{
weightForSelector1 += [_orderedSelectors indexOfObject:selector1];
weightForSelector2 += [_orderedSelectors indexOfObject:selector2];
}
if (weightForSelector1 > weightForSelector2)
{
return (NSComparisonResult)NSOrderedDescending;
}
if (weightForSelector1 < weightForSelector2)
{
return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
}];

// Single part selectors are also weighted by specificity, but since they all have the same weight,
//we apply them in order of least specific to most specific.
[matchingCascadingSelectors addObjectsFromArray:[self matchingSimpleCascadedSelectors:element]];

NSMutableSet *tmpMatchedSelectors;

if (matchedSelectors)
Expand All @@ -713,7 +713,7 @@ - (NSDictionary *)mergedStyleDictionaryForElement:(DTHTMLElement *)element match
}

// Apply complex cascading selectors first, then apply most specific selectors
for (NSString *cascadingSelector in sortedCascadingSelectors)
for (NSString *cascadingSelector in matchingCascadingSelectors)
{
NSDictionary *byCascadingSelector = [_styles objectForKey:cascadingSelector];
[tmpDict addEntriesFromDictionary:byCascadingSelector];
Expand Down Expand Up @@ -805,7 +805,7 @@ - (NSMutableArray *)matchingComplexCascadingSelectorsForElement:(DTHTMLElement *
continue;
}

DTHTMLElement *currentElement = element;
DTHTMLElement *nextElement = element;

// Walking up the hierarchy so start at the right side of the selector and work to the left
// Aside: Manual for loop here is faster than for in with reverseObjectEnumerator
Expand All @@ -816,8 +816,13 @@ - (NSMutableArray *)matchingComplexCascadingSelectorsForElement:(DTHTMLElement *

if (selectorPart.length)
{
while (currentElement != nil)
while (nextElement != nil)
{
DTHTMLElement *currentElement = nextElement;

//This must be set to advance here, above all of the breaks, so the loop properly advances.
nextElement = currentElement.parentElement;

if ([selectorPart characterAtIndex:0] == '#')
{
// If we're at an id and it doesn't match the current element then the style doesn't apply
Expand Down Expand Up @@ -852,7 +857,10 @@ - (NSMutableArray *)matchingComplexCascadingSelectorsForElement:(DTHTMLElement *
break;
}

currentElement = currentElement.parentElement;
// break if the right most portion of the selector doesn't match the target element
if (!matched && ([currentElement isEqual:element])) {
break;
}
}
}

Expand All @@ -861,7 +869,8 @@ - (NSMutableArray *)matchingComplexCascadingSelectorsForElement:(DTHTMLElement *
break;
}

if ([selectorPart isEqualToString:[selectorParts objectAtIndex:0]])
//Only match if we really are on the last part of the selector and all other parts have matched so far
if (j == 0)
{
if (matched && ![matchedSelectors containsObject:selector])
{
Expand Down
29 changes: 0 additions & 29 deletions Core/Source/DTHTMLAttributedStringBuilder.m
Original file line number Diff line number Diff line change
Expand Up @@ -427,35 +427,6 @@ - (void)_registerTagStartHandlers

[textLists addObject:newListStyle];

// workaround for different styles on stacked lists
if ([textLists count]>1) // not necessary for first
{
// find out if each list is ordered or unordered
NSMutableArray *tmpArray = [NSMutableArray array];
for (DTCSSListStyle *oneList in textLists)
{
if ([oneList isOrdered])
{
[tmpArray addObject:@"ol"];
}
else
{
[tmpArray addObject:@"ul"];
}
}

// build a CSS selector
NSString *selector = [tmpArray componentsJoinedByString:@" "];

// find style
NSDictionary *style = [[_globalStyleSheet styles] objectForKey:selector];

if (style)
{
[newListStyle updateFromStyleDictionary:style];
}
}

_currentTag.paragraphStyle.textLists = textLists;
};

Expand Down
8 changes: 8 additions & 0 deletions Core/Test/Resources/CSSOOMCrash.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SkipUnitTest</key>
<true/>
</dict>
</plist>
109 changes: 109 additions & 0 deletions Core/Test/Source/DTHTMLAttributedStringBuilderTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,103 @@ - (void)testPrefixWithNewlines
}];
}

// issue 574
- (void)testCorrectListBullets
{
NSAttributedString *attributedString = [self _attributedStringFromHTMLString:@"<ul><li>1</li><ul><li>2</li><ul><li>3</li></ul></ul></ul>" options:nil];


NSString *string = [attributedString string];
NSRange entireStringRange = NSMakeRange(0, [string length]);

__block NSUInteger lineNumber = 0;

[string enumerateSubstringsInRange:entireStringRange options:NSStringEnumerationByParagraphs usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {

NSAttributedString *attributedSubstring = [attributedString attributedSubstringFromRange:enclosingRange];

NSRange prefixRange = [attributedSubstring rangeOfFieldAtIndex:0];
prefixRange.location++;
prefixRange.length = 1;
NSString *bulletChar = [[attributedSubstring string] substringWithRange:prefixRange];

NSString *expectedChar = nil;

switch (lineNumber)
{
case 0:
{
expectedChar = @"\u2022"; // disc
break;
}

case 1:
{
expectedChar = @"\u25e6"; // circle
break;
}

case 2:
{
expectedChar = @"\u25aa"; // square
break;
}
}

BOOL characterIsCorrect = [bulletChar isEqualToString:expectedChar];
STAssertTrue(characterIsCorrect, @"Bullet Character on UL level %d should be '%@' but is '%@'", lineNumber+1, expectedChar, bulletChar);

lineNumber++;
}];
}

// issue 574
- (void)testMixedListPrefix
{
NSAttributedString *attributedString = [self _attributedStringFromHTMLString:@"<ol><li>1a<ul><li>2a<ol><li>3a</li></ol></li></ul></li></ol>" options:nil];

NSString *string = [attributedString string];
NSRange entireStringRange = NSMakeRange(0, [string length]);

__block NSUInteger lineNumber = 0;

[string enumerateSubstringsInRange:entireStringRange options:NSStringEnumerationByParagraphs usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {

NSAttributedString *attributedSubstring = [attributedString attributedSubstringFromRange:enclosingRange];

NSRange prefixRange = [attributedSubstring rangeOfFieldAtIndex:0];
NSString *prefix = [[attributedSubstring string] substringWithRange:prefixRange];

NSString *expectedPrefix = nil;

switch (lineNumber)
{
case 0:
{
expectedPrefix = @"\t1.\t"; // one
break;
}

case 1:
{
expectedPrefix = @"\t\u25e6\t"; // circle
break;
}

case 2:
{
expectedPrefix = @"\t1.\t"; // one
break;
}
}

BOOL prefixIsCorrect = [prefix isEqualToString:expectedPrefix];
STAssertTrue(prefixIsCorrect, @"Prefix level %d should be '%@' but is '%@'", lineNumber+1, expectedPrefix, prefix);

lineNumber++;
}];
}

#pragma mark - CSS Tests

// issue 544
Expand Down Expand Up @@ -771,4 +868,16 @@ - (void)testCascadedSelectorsWithEqualSpecificityLastDeclarationWins {
STAssertEqualObjects(foregroundHTML2, @"ff0000", @"Color should be red and not green.");
}

// text should be green even though there is a span following the div-div.
- (void)testDivDivSpan
{
NSAttributedString *attributedString = [self _attributedStringFromHTMLString:@"<html><head><style>div div {color:green;}</style></head><body><div><div><span>FOO</span></div></div></body></html>" options:nil];

NSDictionary *attributes1 = [attributedString attributesAtIndex:0 effectiveRange:NULL];
DTColor *foreground1 = [attributes1 foregroundColor];
NSString *foreground1HTML = [foreground1 htmlHexString];
BOOL colorOk1 = ([foreground1HTML isEqualToString:@"008000"]);
STAssertTrue(colorOk1, @"First item should be green");
}

@end
8 changes: 6 additions & 2 deletions DTCoreText.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@
A776DBE91716A8EE00E71F36 /* NSStringParagraphTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A776DBE71716A8EE00E71F36 /* NSStringParagraphTest.m */; };
A77A3E421779BF04000B290B /* NSMutableAttributedStringHTMLTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A77A3E411779BF03000B290B /* NSMutableAttributedStringHTMLTest.m */; };
A77A3E431779BF04000B290B /* NSMutableAttributedStringHTMLTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A77A3E411779BF03000B290B /* NSMutableAttributedStringHTMLTest.m */; };
A783CE7917D11D0700C84C28 /* CSSOOMCrash.plist in Resources */ = {isa = PBXBuildFile; fileRef = A783CE6717D11D0100C84C28 /* CSSOOMCrash.plist */; };
A785FA1217BA113900BB758E /* DTCSSStylesheetTest.m in Sources */ = {isa = PBXBuildFile; fileRef = A7E3346D16837482002EFCBE /* DTCSSStylesheetTest.m */; };
A788C95D14863E8700E1AFD9 /* DTAttributedTextCell.h in Headers */ = {isa = PBXBuildFile; fileRef = A788C91014863E8700E1AFD9 /* DTAttributedTextCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
A788C95E14863E8700E1AFD9 /* DTAttributedTextCell.h in Headers */ = {isa = PBXBuildFile; fileRef = A788C91014863E8700E1AFD9 /* DTAttributedTextCell.h */; settings = {ATTRIBUTES = (Public, ); }; };
Expand Down Expand Up @@ -939,6 +940,7 @@
A776DBE71716A8EE00E71F36 /* NSStringParagraphTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSStringParagraphTest.m; sourceTree = "<group>"; };
A77A3E401779BF03000B290B /* NSMutableAttributedStringHTMLTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSMutableAttributedStringHTMLTest.h; sourceTree = "<group>"; };
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>"; };
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 @@ -1635,6 +1637,7 @@
A7E8E1D316D22B7E001EDE51 /* EmptyLinesAndFontAttribute.html */,
A7343F3217BDF64A00EF9B83 /* CSSCascading.html */,
C2CDBADA17CCD245000E4AD7 /* CSSOOMCrash.html */,
A783CE6717D11D0100C84C28 /* CSSOOMCrash.plist */,
);
path = Resources;
sourceTree = "<group>";
Expand Down Expand Up @@ -2383,6 +2386,7 @@
A730BCD916D29588003B849F /* Languages.html in Resources */,
A7343F3417BDF64A00EF9B83 /* CSSCascading.html in Resources */,
C2CDBAED17CCD5EA000E4AD7 /* CSSOOMCrash.html in Resources */,
A783CE7917D11D0700C84C28 /* CSSOOMCrash.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -3166,7 +3170,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = /usr/include/libxml2;
IPHONEOS_DEPLOYMENT_TARGET = 4.2;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
MACOSX_DEPLOYMENT_TARGET = 10.7;
SDKROOT = iphoneos;
USER_HEADER_SEARCH_PATHS = "\"$(SRCROOT)/Core/Source\"";
Expand All @@ -3184,7 +3188,7 @@
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
HEADER_SEARCH_PATHS = /usr/include/libxml2;
IPHONEOS_DEPLOYMENT_TARGET = 4.2;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
MACOSX_DEPLOYMENT_TARGET = 10.7;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
SDKROOT = iphoneos;
Expand Down
Loading

0 comments on commit f3b8c52

Please sign in to comment.