Skip to content
This repository was archived by the owner on Sep 20, 2023. It is now read-only.

Fix readme duplicate identifier asserts #2219

Merged
merged 4 commits into from
Oct 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 102 additions & 81 deletions Classes/Issues/Comments/Markdown/CMarkParsing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ private extension TextElement {
func build(
_ builder: StyledTextBuilder,
options: CMarkOptions,
context: CMarkContext
context: CMarkContext = CMarkContext()
) -> StyledTextBuilder {
builder.save()
defer { builder.restore() }
Expand Down Expand Up @@ -104,7 +104,7 @@ private extension Sequence where Iterator.Element == TextElement {
func build(
_ builder: StyledTextBuilder,
options: CMarkOptions,
context: CMarkContext
context: CMarkContext = CMarkContext()
) -> StyledTextBuilder {
forEach { $0.build(builder, options: options, context: context) }
return builder
Expand All @@ -116,7 +116,7 @@ private extension ListElement {
func build(_ builder: StyledTextBuilder, options: CMarkOptions) -> StyledTextBuilder {
switch self {
case .text(let text):
text.build(builder, options: options, context: CMarkContext())
text.build(builder, options: options)
case .list(let children, let type, let level):
children.build(builder, options: options, type: type, level: level)
}
Expand All @@ -139,7 +139,7 @@ private extension Array where Iterator.Element == TextLine {
@discardableResult
func build(_ builder: StyledTextBuilder, options: CMarkOptions) -> StyledTextBuilder {
forEach({ el in
el.build(builder, options: options, context: CMarkContext())
el.build(builder, options: options)
}, joined: { _ in
builder.add(text: "\n")
})
Expand All @@ -153,21 +153,15 @@ private extension Array where Iterator.Element == [ListElement] {
_ builder: StyledTextBuilder,
options: CMarkOptions,
type: ListType,
level: Int
level: Int = 0
) -> StyledTextBuilder {
builder.save()
defer { builder.restore() }

let paragraphStyle = ((builder.tipAttributes?[.paragraphStyle] as? NSParagraphStyle)?.mutableCopy() as? NSMutableParagraphStyle)
?? NSMutableParagraphStyle()
paragraphStyle.firstLineHeadIndent = CGFloat(level) * 18
// unicode character to newline without creating a new paragraph to avoid NSParagraphStyle spacing
let newline = "\u{2028}"

for (i, c) in enumerated() {
// tighten spacing for the list after the first paragraph
if i > 0 || level > 0 {
paragraphStyle.paragraphSpacingBefore = 2
}

let tick: String
switch type {
case .ordered:
Expand All @@ -177,17 +171,22 @@ private extension Array where Iterator.Element == [ListElement] {
? Constants.Strings.bullet
: Constants.Strings.bulletHollow
}
builder.add(text: "\(tick) ", attributes: [.paragraphStyle: paragraphStyle])

var spaces = ""
for _ in 0..<level {
spaces += " "
}
builder.add(text: "\(spaces)\(tick) ")

c.forEach({ cc in
cc.build(builder, options: options)
}, joined: { _ in
builder.add(text: "\n")
builder.add(text: newline)
})

// never append whitespace on the last element
if i != count - 1 {
builder.add(text: "\n")
builder.add(text: newline)
}
}
return builder
Expand All @@ -204,17 +203,15 @@ private extension TableRow {
$0.build(
StyledTextBuilder.markdownBase(isRoot: options.isRoot)
.add(traits: .traitBold),
options: options,
context: CMarkContext()
options: options
)
}
case .row(let cells):
builders = cells.map {
$0.build(
StyledTextBuilder.markdownBase(isRoot: options.isRoot)
.add(attributes: [.backgroundColor: backgroundColor]),
options: options,
context: CMarkContext()
options: options
)
}
}
Expand All @@ -241,85 +238,112 @@ private extension Array where Iterator.Element == TableRow {
}
}

private extension Element {
func model(_ options: CMarkOptions, lastElement: Bool) -> ListDiffable? {
switch self {
case .text(let items):
return StyledTextRenderer(
string: items.build(
StyledTextBuilder.markdownBase(isRoot: options.isRoot),
options: options,
context: CMarkContext()
).build(renderMode: .preserve),
private func makeModels(elements: [Element], options: CMarkOptions) -> [ListDiffable] {
var models = [ListDiffable]()
var runningBuilder: StyledTextBuilder?

let makeBuilder: () -> StyledTextBuilder = {
let builder: StyledTextBuilder
if let current = runningBuilder {
builder = current
.add(text: "\n")
} else {
builder = StyledTextBuilder.markdownBase(isRoot: options.isRoot)
}
runningBuilder = builder
return builder
}

let endRunningText: (Bool) -> Void = { isLast in
if let builder = runningBuilder {
models.append(StyledTextRenderer(
string: builder.build(renderMode: .preserve),
contentSizeCategory: options.contentSizeCategory,
inset: IssueCommentTextCell.inset(isLast: lastElement),
inset: IssueCommentTextCell.inset(isLast: isLast),
backgroundColor: .white
).warm(width: options.width)
).warm(width: options.width))
}
runningBuilder = nil
}

for (i, el) in elements.enumerated() {
let isLast = i == elements.count - 1

switch el {
case .text(let items):
items.build(makeBuilder(), options: options)
case .heading(let text, let level):
let style: TextStyle
switch level {
case 1: style = Styles.Text.h1
case 2: style = Styles.Text.h2
case 3: style = Styles.Text.h3
case 4: style = Styles.Text.h4
case 5: style = Styles.Text.h5
default: style = Styles.Text.h6.with(foreground: Styles.Colors.Gray.medium.color)
}

let builder = makeBuilder()
.save()
.add(style: style)

// add bottom spacing
builder.add(attributes: [.baselineOffset: 12])
text.build(builder, options: options)

builder.restore()
case .list(let items, let type):
items.build(makeBuilder(), options: options, type: type)
case .quote(let items, let level):
endRunningText(isLast)

let builder = StyledTextBuilder.markdownBase(isRoot: options.isRoot)
.add(attributes: [.foregroundColor: Styles.Colors.Gray.medium.color])
let string = StyledTextRenderer(
string: items.build(builder, options: options, context: CMarkContext()).build(renderMode: .preserve),
string: items.build(builder, options: options).build(renderMode: .preserve),
contentSizeCategory: options.contentSizeCategory,
inset: IssueCommentQuoteCell.inset(quoteLevel: level),
backgroundColor: .white
).warm(width: options.width)
return IssueCommentQuoteModel(level: level, string: string)
models.append(IssueCommentQuoteModel(level: level, string: string))
case .image(let title, let href):
guard let url = URL(string: href) else { return nil }
endRunningText(isLast)

guard let url = URL(string: href) else { continue }
if url.pathExtension.lowercased() == "svg" {
// hack to workaround the SDWebImage not supporting svg images
// just render it in a webview
return IssueCommentHtmlModel(html: "<img src=\(href) />")
models.append(IssueCommentHtmlModel(html: "<img src=\(href) />"))
} else {
return IssueCommentImageModel(url: url, title: title)
models.append(IssueCommentImageModel(url: url, title: title))
}
case .html(let text):
endRunningText(isLast)

let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else { return nil }
guard !trimmed.isEmpty else { continue }
let baseURL: URL?
if let branch = options.branch {
baseURL = URL(string: "https://github.com/\(options.owner)/\(options.repo)/raw/\(branch)/")
} else {
baseURL = nil
}
return IssueCommentHtmlModel(html: trimmed, baseURL: baseURL)
models.append(IssueCommentHtmlModel(html: trimmed, baseURL: baseURL))
case .hr:
return IssueCommentHrModel()
endRunningText(isLast)

models.append(IssueCommentHrModel())
case .codeBlock(let text, let language):
return CodeBlockElement(text: text, language: language, contentSizeCategory: options.contentSizeCategory)
case .heading(let text, let level):
let builder = StyledTextBuilder.markdownBase(isRoot: options.isRoot)
let style: TextStyle
switch level {
case 1: style = Styles.Text.h1
case 2: style = Styles.Text.h2
case 3: style = Styles.Text.h3
case 4: style = Styles.Text.h4
case 5: style = Styles.Text.h5
default: style = Styles.Text.h6.with(foreground: Styles.Colors.Gray.medium.color)
}
builder.add(style: style)
return StyledTextRenderer(
string: text.build(builder, options: options, context: CMarkContext()).build(renderMode: .preserve),
contentSizeCategory: options.contentSizeCategory,
inset: IssueCommentTextCell.inset(isLast: lastElement),
backgroundColor: .white
).warm(width: options.width)
case .list(let items, let type):
let builder = items.build(
StyledTextBuilder.markdownBase(isRoot: options.isRoot),
options: options,
type: type,
level: 0
)
return StyledTextRenderer(
string: builder.build(renderMode: .preserve),
contentSizeCategory: options.contentSizeCategory,
inset: IssueCommentTextCell.inset(isLast: lastElement),
backgroundColor: .white
).warm(width: options.width)
endRunningText(isLast)

models.append(CodeBlockElement(
text: text,
language: language,
contentSizeCategory: options.contentSizeCategory
))
case .table(let rows):
endRunningText(isLast)

var buckets = [TableBucket]()
var rowHeights = [CGFloat]()

Expand All @@ -328,9 +352,13 @@ private extension Element {
fillBuckets(rows: $0.cells, buckets: &buckets, rowHeights: &rowHeights, fill: $0.fill)
}

return IssueCommentTableModel(buckets: buckets, rowHeights: rowHeights)
models.append(IssueCommentTableModel(buckets: buckets, rowHeights: rowHeights))
}
}

endRunningText(true)

return models
}

private func emptyDescription(options: CMarkOptions) -> ListDiffable {
Expand Down Expand Up @@ -373,14 +401,7 @@ func MarkdownModels(
isRoot: isRoot
)

var models = [ListDiffable]()
let elements = node.flatElements
let count = elements.count
for (i, el) in elements.enumerated() {
if let model = el.model(options, lastElement: i == count - 1) {
models.append(model)
}
}
let models = makeModels(elements: node.flatElements, options: options)
if models.count == 0 {
return [emptyDescription(options: options)]
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import StyledTextKit
extension StyledTextBuilder {
static func markdownBase(isRoot: Bool) -> StyledTextBuilder {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.paragraphSpacingBefore = 12
paragraphStyle.paragraphSpacing = 12
paragraphStyle.lineSpacing = 2
let attributes: [NSAttributedStringKey: Any] = [
.foregroundColor: Styles.Colors.Gray.dark.color,
Expand Down
1 change: 0 additions & 1 deletion Classes/Repository/RepositoryOverviewViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ RepositoryBranchUpdatable

override func fetch(page: NSString?) {
let repo = self.repo
// let contentInset = feed.collectionView.contentInset
let width = view.bounds.width - Styles.Sizes.gutter * 2
let contentSizeCategory = UIContentSizeCategory.preferred
let branch = self.branch
Expand Down
6 changes: 2 additions & 4 deletions FreetimeTests/IssueTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ class IssueTests: XCTestCase {
isRoot: false
)

XCTAssertEqual((models[1] as! StyledTextRenderer).string.allText, "See: [Pitch] Introducing the \"Unwrap or Die\" operator to the standard library")
XCTAssertEqual((models[0] as! StyledTextRenderer).string.allText, "...adoption.\nSee: [Pitch] Introducing the \"Unwrap or Die\" operator to the standard library")
}

func test_URLThatContainsIssueReferenceLinkInDescription() {
Expand All @@ -303,9 +303,7 @@ class IssueTests: XCTestCase {
isRoot: false
)

XCTAssertEqual((models[0] as! StyledTextRenderer).string.allText, "This is the implementation for apple/swift-evolution#793")
XCTAssertEqual((models[1] as! StyledTextRenderer).string.allText, "Note: One of the new tests fails...")

XCTAssertEqual((models[0] as! StyledTextRenderer).string.allText, "This is the implementation for apple/swift-evolution#793\nNote: One of the new tests fails...")
}

}