Skip to content

Commit

Permalink
implemented BR inside LI
Browse files Browse the repository at this point in the history
  • Loading branch information
odrobnik committed Oct 26, 2013
1 parent cbb9354 commit 964dcce
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 74 deletions.
171 changes: 101 additions & 70 deletions Core/Source/DTMarkdownParser.m
Expand Up @@ -230,8 +230,43 @@ - (void)_processCharacters:(NSString *)string allowAutodetection:(BOOL)allowAuto
}
}

- (void)_processLine:(NSString *)line allowAutoDetection:(BOOL)allowAutoDetection
- (void)_processLine:(NSString *)line withIndex:(NSUInteger)lineIndex allowAutoDetection:(BOOL)allowAutoDetection
{
BOOL hasNewline = NO;
BOOL needsBR = NO;
BOOL allowLineBreak = [self _shouldAllowLineBreakAfterLineAtIndex:lineIndex];

if (allowLineBreak)
{
line = [line stringByReplacingOccurrencesOfString:@"\r\n" withString:@"\n"];

if ([line hasSuffix:@"\n"] && (_options && DTMarkdownParserOptionGitHubLineBreaks))
{
line = [line substringToIndex:[line length]-1];
needsBR = YES;

}
else if ([line hasSuffix:@" \n"])
{
needsBR = YES;

line = [line substringToIndex:[line length]-3];
}
}
else
{
if ([line hasSuffix:@"\n"])
{
hasNewline = YES;
line = [line substringToIndex:[line length]-1];
}

if ([line hasSuffix:@"\r"])
{
line = [line substringToIndex:[line length]-1];
}
}

NSScanner *scanner = [NSScanner scannerWithString:line];
scanner.charactersToBeSkipped = nil;

Expand Down Expand Up @@ -275,7 +310,7 @@ - (void)_processLine:(NSString *)line allowAutoDetection:(BOOL)allowAutoDetectio
[self _pushTag:@"a" attributes:linkAttributes];

// might contain further markdown/images
[self _processLine:enclosedString allowAutoDetection:NO];
[self _processLine:enclosedString withIndex:lineIndex allowAutoDetection:NO];

[self _popTag];
}
Expand Down Expand Up @@ -324,6 +359,12 @@ - (void)_processLine:(NSString *)line allowAutoDetection:(BOOL)allowAutoDetectio
}
}
}

if (needsBR)
{
[self _pushTag:@"br" attributes:nil];
[self _popTag];
}
}

- (NSUInteger)_indentationLevelForLine:(NSString *)line
Expand Down Expand Up @@ -352,22 +393,59 @@ - (NSUInteger)_indentationLevelForLine:(NSString *)line
return (NSUInteger)floor((spacesCount/4.0));
}


- (BOOL)_shouldCloseListItemAfterLineAtIndex:(NSUInteger)lineIndex
{
NSString *specialTypeOfFollowingLine = _specialLines[@(lineIndex+1)];

if (specialTypeOfFollowingLine != DTMarkdownParserSpecialSubList)
// following line is a sub list, indent does not matter because we deal with opening/closing separately
if (specialTypeOfFollowingLine == DTMarkdownParserSpecialSubList)
{
return NO;
}

// normal paragraph follows
if (!specialTypeOfFollowingLine && ![_ignoredLines containsIndex:lineIndex+1])
{
return NO;
}

return YES;
}

- (BOOL)_shouldAllowLineBreakAfterLineAtIndex:(NSUInteger)lineIndex
{
NSRange lineRange = [_lineRanges[lineIndex] rangeValue];
NSRange paragraphRange = [self _rangeOfParagraphAtIndex:lineRange.location];

BOOL lineIsLastInParagraph = (NSMaxRange(lineRange) == NSMaxRange(paragraphRange));

if (lineIsLastInParagraph)
{
return NO;
}

NSString *specialLineType = _specialLines[@(lineIndex)];
NSString *specialLineTypeOfFollowingLine = _specialLines[@(lineIndex+1)];

if (specialLineType == DTMarkdownParserSpecialTagH1 || specialLineType == DTMarkdownParserSpecialTagH2)
{
return NO;
}

if (![_ignoredLines containsIndex:lineIndex+1] && !specialLineTypeOfFollowingLine)
{
return YES;
}

return NO;
}


- (void)_processListLine:(NSString *)line lineIndex:(NSUInteger)lineIndex
- (void)_processListLineAtLineIndex:(NSUInteger)lineIndex
{
NSValue *value = _lineRanges[lineIndex];
NSRange lineRange = [value rangeValue];
NSString *line = [_string substringWithRange:lineRange];

NSString *prefix;

NSString *specialTypeOfLine = _specialLines[@(lineIndex)];
Expand Down Expand Up @@ -455,8 +533,9 @@ - (void)_processListLine:(NSString *)line lineIndex:(NSUInteger)lineIndex

[self _pushTag:@"li" attributes:nil];


// process line as normal without prefix
[self _processLine:line allowAutoDetection:YES];
[self _processLine:line withIndex:lineIndex allowAutoDetection:YES];

if ([self _shouldCloseListItemAfterLineAtIndex:lineIndex])
{
Expand Down Expand Up @@ -673,24 +752,31 @@ - (void)_findAndMarkSpecialLines

BOOL currentLineIsIgnored = [_ignoredLines containsIndex:lineIndex];
BOOL currentLineIsHR = (_specialLines[@(lineIndex)] == DTMarkdownParserSpecialTagHR);
BOOL currentLineBeginsList = (_specialLines[@(lineIndex)] == DTMarkdownParserSpecialList);

if (currentLineIsIgnored || [scanner isAtEnd] || currentLineIsHR)
if (currentLineIsIgnored || [scanner isAtEnd] || currentLineIsHR || currentLineBeginsList)
{
NSRange netParagraphRange = paragraphRange;

if (currentLineIsIgnored || currentLineIsHR)
if (currentLineIsIgnored || currentLineIsHR || currentLineBeginsList)
{
netParagraphRange.length -= lineRange.length;
}

[_paragraphRanges addObject:[NSValue valueWithRange:netParagraphRange]];
if (netParagraphRange.length)
{
[_paragraphRanges addObject:[NSValue valueWithRange:netParagraphRange]];
}

if (currentLineIsIgnored || currentLineIsHR)
{
[_paragraphRanges addObject:[NSValue valueWithRange:lineRange]];
paragraphRange = NSMakeRange(paragraphRange.location + paragraphRange.length, 0);
}
else
{
paragraphRange = lineRange;
}

paragraphRange = NSMakeRange(paragraphRange.location + paragraphRange.length, 0);
}

[_lineRanges addObject:[NSValue valueWithRange:lineRange]];
Expand Down Expand Up @@ -751,20 +837,6 @@ - (BOOL)parse
NSString *specialLine = _specialLines[@(lineIndex)];
NSString *specialFollowingLine = _specialLines[@(lineIndex+1)];
BOOL followingLineIsIgnored = [_ignoredLines containsIndex:lineIndex+1];

BOOL hasNL = NO;

if ([line hasSuffix:@"\r\n"])
{
line = [line substringToIndex:[line length]-2];
hasNL = YES;
}
else if ([line hasSuffix:@"\n"])
{
line = [line substringToIndex:[line length]-1];
hasNL = YES;
}

BOOL lineIsLastInParagraph = NO;

if (NSMaxRange(lineRange) == NSMaxRange(paragraphRange))
Expand Down Expand Up @@ -792,7 +864,7 @@ - (BOOL)parse
}
else if (specialLine == DTMarkdownParserSpecialList || specialLine == DTMarkdownParserSpecialSubList)
{
[self _processListLine:line lineIndex:lineIndex];
[self _processListLineAtLineIndex:lineIndex];

return;
}
Expand Down Expand Up @@ -823,11 +895,6 @@ - (BOOL)parse
[self _pushTag:@"code" attributes:nil];
}

if (hasNL)
{
codeLine = [codeLine stringByAppendingString:@"\n"];
}

[self _reportCharacters:codeLine];

if (lineIsLastInParagraph)
Expand Down Expand Up @@ -863,7 +930,7 @@ - (BOOL)parse
}

// trim off trailing hashes
while ([line hasSuffix:@"#"])
while ([line hasSuffix:@"#"] || [line hasSuffix:@"#\n"])
{
line = [line substringToIndex:[line length]-1];
}
Expand All @@ -890,36 +957,6 @@ - (BOOL)parse
}

BOOL willCloseTag = (lineIsLastInParagraph || headerLevel || followingLineIsIgnored || specialFollowingLine == DTMarkdownParserSpecialList || specialFollowingLine == DTMarkdownParserSpecialTagHR);
BOOL needsBR = NO;

// handle new lines
if (!lineIsLastInParagraph && !headerLevel)
{
// not a paragraph break

if (_options & DTMarkdownParserOptionGitHubLineBreaks)
{
needsBR = YES;
}
else
{
if ([line hasSuffix:@" "])
{
// two spaces at end of line are "Gruber-style BR"
needsBR = YES;

// trim off trailing spaces
while ([line hasSuffix:@" "])
{
line = [line substringToIndex:[line length]-1];
}
}
else if (!willCloseTag)
{
line = [line stringByAppendingString:@"\n"];
}
}
}

if (needsPushTag)
{
Expand All @@ -939,13 +976,7 @@ - (BOOL)parse
}
}

[self _processLine:line allowAutoDetection:YES];

if (needsBR)
{
[self _pushTag:@"br" attributes:nil];
[self _popTag];
}
[self _processLine:line withIndex:lineIndex allowAutoDetection:YES];

if (willCloseTag)
{
Expand Down
1 change: 1 addition & 0 deletions DTMarkdownParser.xcodeproj/project.pbxproj
Expand Up @@ -2851,6 +2851,7 @@
A7248B30181BC5E90021A209 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A7870C571817F6C000E39311 /* Build configuration list for PBXNativeTarget "DTMarkdownParser (iOS)" */ = {
isa = XCConfigurationList;
Expand Down
20 changes: 16 additions & 4 deletions Test/Source/DTMarkdownParserTest.m
Expand Up @@ -635,6 +635,21 @@ - (void)testHeading2WithFollowingParagraphAndGitHubLineBreaks
STAssertEqualObjects(actual, expected, @"Expected result did not match");
}

- (void)testHeading1WithHashesFollowedBySpace
{
NSString *string = @"# Heading 1 # ";

DTMarkdownParser *parser = [self _parserForString:string options:DTMarkdownParserOptionGitHubLineBreaks];

BOOL result = [parser parse];
STAssertTrue(result, @"Parser should return YES");

NSString *expected = @"<h1>Heading 1 #</h1>\n";
NSString *actual = [self _HTMLFromInvocations];

STAssertEqualObjects(actual, expected, @"Expected result did not match");
}


#pragma mark - Line Break

Expand Down Expand Up @@ -668,7 +683,6 @@ - (void)testGruberLineBreaks

#pragma mark - Hanging Paragraphs

/*
- (void)testHangingOnList
{
NSString *string = @"- one \ntwo";
Expand All @@ -677,13 +691,11 @@ - (void)testHangingOnList
BOOL result = [parser parse];
STAssertTrue(result, @"Parser should return YES");

NSString *expected = @"<p>Line1<br />Line2</p>\n<p>Line3</p>\n";
NSString *expected = @"<ul><li>one<br />two</li></ul>";
NSString *actual = [self _HTMLFromInvocations];

STAssertEqualObjects(actual, expected, @"Expected result did not match");
}
*/

#pragma mark - Horizontal Rule

Expand Down

0 comments on commit 964dcce

Please sign in to comment.