This commit is contained in:
Simon Fairbairn 2020-01-30 11:46:12 +13:00
parent a209277d97
commit 19c473e81d
10 changed files with 109 additions and 45 deletions

View File

@ -63,8 +63,8 @@ GEM
dotenv (2.7.5)
emoji_regex (1.0.1)
escape (0.0.4)
excon (0.71.1)
faraday (0.17.1)
excon (0.72.0)
faraday (0.17.3)
multipart-post (>= 1.2, < 3)
faraday-cookie_jar (0.0.6)
faraday (>= 0.7.4)
@ -72,7 +72,7 @@ GEM
faraday_middleware (0.13.1)
faraday (>= 0.7.4, < 1.0)
fastimage (2.1.7)
fastlane (2.138.0)
fastlane (2.140.0)
CFPropertyList (>= 2.3, < 4.0.0)
addressable (>= 2.3, < 3.0.0)
babosa (>= 1.0.2, < 2.0.0)
@ -87,7 +87,7 @@ GEM
faraday_middleware (~> 0.13.1)
fastimage (>= 2.1.0, < 3.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-api-client (>= 0.21.2, < 0.24.0)
google-api-client (>= 0.29.2, < 0.37.0)
google-cloud-storage (>= 1.15.0, < 2.0.0)
highline (>= 1.7.2, < 2.0.0)
json (< 3.0.0)
@ -112,30 +112,34 @@ GEM
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
google-api-client (0.23.9)
google-api-client (0.36.4)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.5, < 0.7.0)
googleauth (~> 0.9)
httpclient (>= 2.8.1, < 3.0)
mime-types (~> 3.0)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.0)
signet (~> 0.9)
google-cloud-core (1.4.1)
signet (~> 0.12)
google-cloud-core (1.5.0)
google-cloud-env (~> 1.0)
google-cloud-errors (~> 1.0)
google-cloud-env (1.3.0)
faraday (~> 0.11)
google-cloud-storage (1.16.0)
google-cloud-errors (1.0.0)
google-cloud-storage (1.25.1)
addressable (~> 2.5)
digest-crc (~> 0.4)
google-api-client (~> 0.23)
google-api-client (~> 0.33)
google-cloud-core (~> 1.2)
googleauth (>= 0.6.2, < 0.10.0)
googleauth (0.6.7)
googleauth (~> 0.9)
mini_mime (~> 1.0)
googleauth (0.10.0)
faraday (~> 0.12)
jwt (>= 1.4, < 3.0)
memoist (~> 0.16)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (~> 0.7)
signet (~> 0.12)
highline (1.7.10)
http-cookie (1.0.3)
domain_name (~> 0.5)
@ -145,11 +149,9 @@ GEM
json (2.3.0)
jwt (2.1.0)
memoist (0.16.2)
mime-types (3.3)
mime-types-data (~> 3.2015)
mime-types-data (3.2019.1009)
mini_magick (4.9.5)
minitest (5.13.0)
mini_magick (4.10.1)
mini_mime (1.0.2)
minitest (5.14.0)
molinillo (0.6.6)
multi_json (1.14.1)
multi_xml (0.6.0)
@ -183,17 +185,17 @@ GEM
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
tty-cursor (0.7.0)
tty-cursor (0.7.1)
tty-screen (0.7.0)
tty-spinner (0.9.2)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
tzinfo (1.2.5)
tzinfo (1.2.6)
thread_safe (~> 0.1)
uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.6)
unicode-display_width (1.6.0)
unicode-display_width (1.6.1)
word_wrap (1.0.0)
xcodeproj (1.14.0)
CFPropertyList (>= 2.3.3, < 4.0)
@ -214,4 +216,4 @@ DEPENDENCIES
fastlane
BUNDLED WITH
2.0.2
2.1.4

View File

@ -56,6 +56,7 @@
F4CE98E61C8AF01300D735C1 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
F4CE98E71C8AF01300D735C1 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
F4CE98E81C8AF01300D735C1 /* SwiftyMarkdown.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SwiftyMarkdown.podspec; sourceTree = "<group>"; };
F4FEF07423E13365007219EF /* metadataTest.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = metadataTest.md; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -117,6 +118,7 @@
isa = PBXGroup;
children = (
F4A48ABA23A8518900713437 /* test.md */,
F4FEF07423E13365007219EF /* metadataTest.md */,
F4CE98901C8A921300D735C1 /* SwiftyMarkdownLineTests.swift */,
F40D3A7E23A807F60085CF6E /* SwiftyMarkdownCharacterTests.swift */,
F4CE98921C8A921300D735C1 /* Info.plist */,

View File

@ -38,6 +38,7 @@ public enum Remove {
public enum ChangeApplication {
case current
case previous
case untilClose
}
public struct LineRule {
@ -58,6 +59,7 @@ public struct LineRule {
public class SwiftyLineProcessor {
var closeToken : String? = nil
let defaultType : LineStyling
public var processEmptyStrings : LineStyling?
let lineRules : [LineRule]
@ -87,18 +89,12 @@ public class SwiftyLineProcessor {
return output
}
func processLineLevelAttributes( _ text : String ) -> SwiftyLine {
func processLineLevelAttributes( _ text : String ) -> SwiftyLine? {
if text.isEmpty, let style = processEmptyStrings {
return SwiftyLine(line: "", lineStyle: style)
}
let previousLines = lineRules.filter({ $0.changeAppliesTo == .previous })
for element in previousLines {
let output = (element.shouldTrim) ? text.trimmingCharacters(in: .whitespaces) : text
let charSet = CharacterSet(charactersIn: element.token )
if output.unicodeScalars.allSatisfy({ charSet.contains($0) }) {
return SwiftyLine(line: "", lineStyle: element.type)
}
}
for element in lineRules {
guard element.token.count > 0 else {
continue
@ -106,6 +102,10 @@ public class SwiftyLineProcessor {
var output : String = (element.shouldTrim) ? text.trimmingCharacters(in: .whitespaces) : text
let unprocessed = output
if let hasToken = self.closeToken, unprocessed != hasToken {
return nil
}
switch element.removeFrom {
case .leading:
output = findLeadingLineElement(element, in: output)
@ -114,6 +114,8 @@ public class SwiftyLineProcessor {
case .both:
output = findLeadingLineElement(element, in: output)
output = findTrailingLineElement(element, in: output)
case .entireLine:
output = findLeadingLineElement(element, in: output)
default:
break
}
@ -121,11 +123,26 @@ public class SwiftyLineProcessor {
guard unprocessed != output else {
continue
}
if element.changeAppliesTo == .untilClose {
self.closeToken = (self.closeToken == nil) ? element.token : nil
return nil
}
output = (element.shouldTrim) ? output.trimmingCharacters(in: .whitespaces) : output
return SwiftyLine(line: output, lineStyle: element.type)
}
for element in previousLines {
let output = (element.shouldTrim) ? text.trimmingCharacters(in: .whitespaces) : text
let charSet = CharacterSet(charactersIn: element.token )
if output.unicodeScalars.allSatisfy({ charSet.contains($0) }) {
return SwiftyLine(line: "", lineStyle: element.type)
}
}
return SwiftyLine(line: text.trimmingCharacters(in: .whitespaces), lineStyle: defaultType)
}
@ -137,8 +154,9 @@ public class SwiftyLineProcessor {
continue
}
let input : SwiftyLine
input = processLineLevelAttributes(String(heading))
guard let input = processLineLevelAttributes(String(heading)) else {
continue
}
if let existentPrevious = input.lineStyle.styleIfFoundStyleAffectsPreviousLine(), foundAttributes.count > 0 {
if let idx = foundAttributes.firstIndex(of: foundAttributes.last!) {

View File

@ -140,6 +140,8 @@ extension SwiftyMarkdown {
func color( for line : SwiftyLine ) -> UIColor {
// What type are we and is there a font name set?
switch line.lineStyle as! MarkdownLineStyle {
case .yaml:
return body.color
case .h1, .previousH1:
return h1.color
case .h2, .previousH2:

View File

@ -38,7 +38,7 @@ enum MarkdownLineStyle : LineStyling {
}
}
case yaml
case h1
case h2
case h3
@ -125,6 +125,7 @@ If that is not set, then the system default will be used.
/// A class that takes a [Markdown](https://daringfireball.net/projects/markdown/) string or file and returns an NSAttributedString with the applied styles. Supports Dynamic Type.
@objc open class SwiftyMarkdown: NSObject {
static public var lineRules = [
LineRule(token: "=", type: MarkdownLineStyle.previousH1, removeFrom: .entireLine, changeAppliesTo: .previous),
LineRule(token: "-", type: MarkdownLineStyle.previousH2, removeFrom: .entireLine, changeAppliesTo: .previous),
LineRule(token: " ", type: MarkdownLineStyle.codeblock, removeFrom: .leading, shouldTrim: false),
@ -140,11 +141,11 @@ If that is not set, then the system default will be used.
]
static public var characterRules = [
CharacterRule(openTag: "![", intermediateTag: "](", closingTag: ")", escapeCharacter: "\\", styles: [1 : [CharacterStyle.image]], maxTags: 1),
// CharacterRule(openTag: "![", intermediateTag: "](", closingTag: ")", escapeCharacter: "\\", styles: [1 : [CharacterStyle.image]], maxTags: 1),
CharacterRule(openTag: "[", intermediateTag: "](", closingTag: ")", escapeCharacter: "\\", styles: [1 : [CharacterStyle.link]], maxTags: 1),
CharacterRule(openTag: "`", intermediateTag: nil, closingTag: nil, escapeCharacter: "\\", styles: [1 : [CharacterStyle.code]], maxTags: 1, cancels: .allRemaining),
// CharacterRule(openTag: "`", intermediateTag: nil, closingTag: nil, escapeCharacter: "\\", styles: [1 : [CharacterStyle.code]], maxTags: 1, cancels: .allRemaining),
CharacterRule(openTag: "*", intermediateTag: nil, closingTag: nil, escapeCharacter: "\\", styles: [1 : [CharacterStyle.italic], 2 : [CharacterStyle.bold], 3 : [CharacterStyle.bold, CharacterStyle.italic]], maxTags: 3),
CharacterRule(openTag: "_", intermediateTag: nil, closingTag: nil, escapeCharacter: "\\", styles: [1 : [CharacterStyle.italic], 2 : [CharacterStyle.bold], 3 : [CharacterStyle.bold, CharacterStyle.italic]], maxTags: 3)
// CharacterRule(openTag: "_", intermediateTag: nil, closingTag: nil, escapeCharacter: "\\", styles: [1 : [CharacterStyle.italic], 2 : [CharacterStyle.bold], 3 : [CharacterStyle.bold, CharacterStyle.italic]], maxTags: 3)
]
let lineProcessor = SwiftyLineProcessor(rules: SwiftyMarkdown.lineRules, defaultRule: MarkdownLineStyle.body)

View File

@ -193,6 +193,7 @@ public class SwiftyTokeniser {
continue
}
if let hasReplacement = self.replacements[token.inputString] {
os_log("Found replacement for %@", log: .tokenising, type: .info, token.inputString)
for var repToken in hasReplacement {
guard repToken.type == .string else {
finalTokens.append(repToken)
@ -248,10 +249,13 @@ public class SwiftyTokeniser {
var outputTokens : [Token] = []
let scanner = Scanner(string: stringToken.outputString)
scanner.charactersToBeSkipped = nil
var repTokens = replacements
// Remove any replacements that don't appear in the incoming string
var repTokens = replacements.filter({ stringToken.outputString.contains($0.inputString) })
var testString = "\n"
while !scanner.isAtEnd {
var outputString : String = ""
var testString = "\n"
if repTokens.count > 0 {
testString = repTokens.removeFirst().inputString
}

View File

@ -4,7 +4,7 @@ SwiftyMarkdown is a Swift-based *Markdown* parser that converts *Markdown* files
Show Images From Your App Bundle!
---
![Image](bubble)
![Image](bubble) There may be a problem with [Links](https://www.neverendingvoyage.com/).
Customise fonts and colors easily in a Swift-like way:

View File

@ -13,9 +13,11 @@ import XCTest
class SwiftyMarkdownCharacterTests: XCTestCase {
func testIsolatedCase() {
let challenge = TokenTest(input: "[Link1](http://voyagetravelapps.com/) test, testing another link [Link2](http://voyagetravelapps.com/)", output: "Link1 test, testing another link Link2", tokens: [
let challenge = TokenTest(input: "[Link1](http://voyagetravelapps.com/) **bold** [Link2](http://voyagetravelapps.com/)", output: "Link1 bold Link2", tokens: [
Token(type: .string, inputString: "Link1", characterStyles: [CharacterStyle.link]),
Token(type: .string, inputString: " test, testing another link ", characterStyles: []),
Token(type: .string, inputString: " ", characterStyles: []),
Token(type: .string, inputString: "bold", characterStyles: [CharacterStyle.bold]),
Token(type: .string, inputString: " ", characterStyles: []),
Token(type: .string, inputString: "Link2", characterStyles: [CharacterStyle.link])
])
let results = self.attempt(challenge)
@ -490,6 +492,19 @@ class SwiftyMarkdownCharacterTests: XCTestCase {
XCTAssertEqual(results.foundStyles, results.expectedStyles)
XCTAssertEqual(results.attributedString.string, challenge.output)
challenge = TokenTest(input: "[Link1](http://voyagetravelapps.com/) **bold** [Link2](http://voyagetravelapps.com/)", output: "Link1 bold Link2", tokens: [
Token(type: .string, inputString: "Link1", characterStyles: [CharacterStyle.link]),
Token(type: .string, inputString: " ", characterStyles: []),
Token(type: .string, inputString: "bold", characterStyles: [CharacterStyle.bold]),
Token(type: .string, inputString: " ", characterStyles: []),
Token(type: .string, inputString: "Link2", characterStyles: [CharacterStyle.link])
])
results = self.attempt(challenge)
XCTAssertEqual(challenge.tokens.count, results.stringTokens.count)
XCTAssertEqual(results.tokens.map({ $0.outputString }).joined(), challenge.output)
XCTAssertEqual(results.foundStyles, results.expectedStyles)
XCTAssertEqual(results.attributedString.string, challenge.output)
}
func testLinksWithOtherStyles() {

View File

@ -139,4 +139,10 @@ class SwiftyMarkdownTests: XCTestCase {
XCTAssertEqual(output, expected)
}
func testThatYAMLMetadataIsRemoved() {
let yaml = StringTest(input: "---\nlayout: page\ntitle: \"Trail Wallet FAQ\"\ndate: 2015-04-22 10:59\ncomments: true\nsharing: true\nliking: false\nfooter: true\nsidebar: false\n---\n# Finally some Markdown!", expectedOutput: "Finally some Markdown!")
let md = SwiftyMarkdown(string: yaml.input)
XCTAssertEqual(md.attributedString().string, yaml.expectedOutput)
}
}

View File

@ -0,0 +1,14 @@
---
layout: page
title: "Trail Wallet FAQ"
date: 2015-04-22 10:59
comments: true
sharing: true
liking: false
footer: true
sidebar: false
---
# Good Day To You, Walleteer!
We are Erin and Simon from [Never Ending Voyage][1] and we want to thank you for trying out our app. We have been travelling non-stop for seven years and part of how we support ourselves is through Trail Wallet.