Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🎨 Improving API structure for readability #460

Merged
merged 2 commits into from
Aug 23, 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
8 changes: 8 additions & 0 deletions Macaw.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,8 @@
5BFEF5D120B80A83008DAC11 /* ColorMatrixEffect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BFEF5CD20B80A83008DAC11 /* ColorMatrixEffect.swift */; };
5BFEF5D620BC1C1F008DAC11 /* paths-data-18-f-manual.svg in Resources */ = {isa = PBXBuildFile; fileRef = 5BFEF5D420BC1C1E008DAC11 /* paths-data-18-f-manual.svg */; };
5BFEF5D720BC1C1F008DAC11 /* paths-data-18-f-manual.reference in Resources */ = {isa = PBXBuildFile; fileRef = 5BFEF5D520BC1C1F008DAC11 /* paths-data-18-f-manual.reference */; };
6A616BFA2129560A006A07FA /* MacawTests.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 6A616BF92129560A006A07FA /* MacawTests.bundle */; };
6A616BFC212964E8006A07FA /* SVGParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A616BFB212964E8006A07FA /* SVGParserTest.swift */; };
A718CD441F45C28200966E06 /* Common_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD431F45C28200966E06 /* Common_iOS.swift */; };
A718CD471F45C28700966E06 /* Graphics_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD451F45C28700966E06 /* Graphics_iOS.swift */; };
A718CD481F45C28700966E06 /* MView_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = A718CD461F45C28700966E06 /* MView_iOS.swift */; };
Expand Down Expand Up @@ -877,6 +879,8 @@
5BFEF5CD20B80A83008DAC11 /* ColorMatrixEffect.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorMatrixEffect.swift; sourceTree = "<group>"; };
5BFEF5D420BC1C1E008DAC11 /* paths-data-18-f-manual.svg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "paths-data-18-f-manual.svg"; sourceTree = "<group>"; };
5BFEF5D520BC1C1F008DAC11 /* paths-data-18-f-manual.reference */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "paths-data-18-f-manual.reference"; sourceTree = "<group>"; };
6A616BF92129560A006A07FA /* MacawTests.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = MacawTests.bundle; sourceTree = "<group>"; };
6A616BFB212964E8006A07FA /* SVGParserTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SVGParserTest.swift; sourceTree = "<group>"; };
A718CD431F45C28200966E06 /* Common_iOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Common_iOS.swift; path = Source/platform/iOS/Common_iOS.swift; sourceTree = SOURCE_ROOT; };
A718CD451F45C28700966E06 /* Graphics_iOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Graphics_iOS.swift; path = Source/platform/iOS/Graphics_iOS.swift; sourceTree = SOURCE_ROOT; };
A718CD461F45C28700966E06 /* MView_iOS.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MView_iOS.swift; path = Source/platform/iOS/MView_iOS.swift; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -1289,6 +1293,7 @@
57FCD27A1D76EA4600CC0FB6 /* MacawTests */ = {
isa = PBXGroup;
children = (
6A616BF92129560A006A07FA /* MacawTests.bundle */,
A7E675541EC4211E00BD9ECB /* Bounds */,
5713C4F11E5AD35900BBA4D9 /* Animation */,
57CAB1241D7832E000FD8E47 /* svg */,
Expand All @@ -1298,6 +1303,7 @@
C4820B191F458D64008CE0FF /* MacawSVGTests.swift */,
5BAE2057208F24DE006BF277 /* SceneSerialization.swift */,
57FCD27D1D76EA4600CC0FB6 /* Info.plist */,
6A616BFB212964E8006A07FA /* SVGParserTest.swift */,
);
path = MacawTests;
sourceTree = "<group>";
Expand Down Expand Up @@ -1788,6 +1794,7 @@
5B1AE27420B6A669007EECCB /* color-prop-02-f-manual.svg in Resources */,
5B1AE25120B6A669007EECCB /* coords-trans-05-t-manual.reference in Resources */,
5B1AE29120B6A669007EECCB /* coords-transformattr-01-f-manual.svg in Resources */,
6A616BFA2129560A006A07FA /* MacawTests.bundle in Resources */,
5B1AE2D320B6A669007EECCB /* shapes-rect-04-f-manual.reference in Resources */,
5B1AE23C20B6A669007EECCB /* paths-data-15-t-manual.svg in Resources */,
5BAE2039208E163D006BF277 /* polygon.reference in Resources */,
Expand Down Expand Up @@ -2222,6 +2229,7 @@
5713C4F31E5AD46800BBA4D9 /* ControlStatesTests.swift in Sources */,
57FCD27C1D76EA4600CC0FB6 /* MacawTests.swift in Sources */,
A7E675561EC4213500BD9ECB /* NodeBoundsTests.swift in Sources */,
6A616BFC212964E8006A07FA /* SVGParserTest.swift in Sources */,
57E0EB2E1EB34CDD00638039 /* AnimationUtilsTests.swift in Sources */,
5713C4F51E5AE2C300BBA4D9 /* CombineAnimationTests.swift in Sources */,
57CAB1231D782DFC00FD8E47 /* TestUtils.swift in Sources */,
Expand Down
29 changes: 16 additions & 13 deletions MacawTests/MacawSVGTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,24 @@ class MacawSVGTests: XCTestCase {
}
}

func validate(_ test: String) {
func validate(_ testResource: String) {
let bundle = Bundle(for: type(of: TestUtils()))
do {
let node = try SVGParser.parse(bundle: bundle, path: test)
validate(node: node, referenceFile: test)
let node = try SVGParser.parse(bundle: bundle, path: testResource)
validate(node: node, referenceFile: testResource)
let node2 = try SVGParser.parse(resource: testResource, fromBundle: bundle)
validate(node: node2, referenceFile: testResource)
} catch {
print(error)
XCTFail()
}
}


func create(_ test: String) {
func create(_ testResource: String) {
let bundle = Bundle(for: type(of: TestUtils()))
do {
let path = bundle.path(forResource: test, ofType: "svg")?.replacingOccurrences(of: ".svg", with: ".reference")
let node = try SVGParser.parse(bundle: bundle, path: test)
let path = bundle.path(forResource: testResource, ofType: "svg")?.replacingOccurrences(of: ".svg", with: ".reference")
let node = try SVGParser.parse(bundle: bundle, path: testResource)
let result = SVGSerializer.serialize(node: node)
try result.write(to: URL(fileURLWithPath: path!), atomically: true, encoding: String.Encoding.utf8)
} catch {
Expand Down Expand Up @@ -175,21 +176,23 @@ class MacawSVGTests: XCTestCase {
}
}

func validateJSON(_ test: String) {
func validateJSON(_ testResource: String) {
let bundle = Bundle(for: type(of: TestUtils()))
do {
let node = try SVGParser.parse(bundle: bundle, path: test)
validateJSON(node: node, referenceFile: test)
let node = try SVGParser.parse(bundle: bundle, path: testResource)
validateJSON(node: node, referenceFile: testResource)
let node2 = try SVGParser.parse(resource: testResource, fromBundle: bundle)
validateJSON(node: node2, referenceFile: testResource)
} catch {
XCTFail(error.localizedDescription)
}
}

func createJSON(_ test: String) {
func createJSON(_ testResource: String) {
let bundle = Bundle(for: type(of: TestUtils()))
do {
let path = bundle.path(forResource: test, ofType: "svg")?.replacingOccurrences(of: ".svg", with: ".reference")
let node = try SVGParser.parse(bundle: bundle, path: test)
let path = bundle.path(forResource: testResource, ofType: "svg")?.replacingOccurrences(of: ".svg", with: ".reference")
let node = try SVGParser.parse(bundle: bundle, path: testResource)
guard let serializableNode = node as? Serializable else {
XCTFail()
return
Expand Down
1 change: 1 addition & 0 deletions MacawTests/MacawTests.bundle/circle.reference
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" ><g><g><circle r="40" cy="50" cx="50" fill="red" stroke="black" stroke-width="3.0"/><circle r="40" cy="50" cx="140" fill="#F0F0AA" stroke="black" stroke-width="3.0"/></g></g></svg>
1 change: 1 addition & 0 deletions MacawTests/MacawTests.bundle/circle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
43 changes: 43 additions & 0 deletions MacawTests/SVGParserTest.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// SVGParserTest.swift
// MacawTests
//
// Created by Julius Lundang on 19/08/2018.
// Copyright © 2018 Exyte. All rights reserved.
//

import XCTest
@testable import Macaw

class SVGParserTest: XCTestCase {
func testParseFromOtherBundle() {
let bundle = Bundle(for: type(of: TestUtils()))
let bundleMacawTestsURL = bundle.resourceURL?.appendingPathComponent("MacawTests.bundle")
let macawTestsBundle = Bundle(url: bundleMacawTestsURL!)!
do {
let node = try SVGParser.parse(resource: "circle", fromBundle: macawTestsBundle)
XCTAssertNotNil(node)
if let fullPath = macawTestsBundle.path(forResource: "circle", ofType: "svg") {
let node2 = try SVGParser.parse(fullPath: fullPath)
XCTAssertNotNil(node2)
} else {
XCTFail("No circle.svg found")
}
} catch {
XCTFail(error.localizedDescription)
}
}

func testParseGivenInvalidPath() {
let fullPath = "invalid fullPath"
XCTAssertThrowsError(try SVGParser.parse(fullPath: fullPath)) { error in
XCTAssertEqual(error as! SVGParserError, SVGParserError.noSuchFile(path: "invalid fullPath"))
}
}

func testParseGiventEmptyPath() {
XCTAssertThrowsError(try SVGParser.parse(fullPath: "")) { error in
XCTAssertEqual(error as! SVGParserError, SVGParserError.noSuchFile(path: ""))
}
}
}
50 changes: 47 additions & 3 deletions Source/svg/SVGParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,65 @@ import SWXMLHash
open class SVGParser {

/// Parse an SVG file identified by the specified bundle, name and file extension.
/// - returns: Root node of the corresponding Macaw scene.
///
/// - Parameters:
/// - bundle: Bundle resource
/// - path: Resource filename
/// - ofType: Type of resource file. The default is "svg"
/// - Returns: Root node of the corresponding Macaw scene.
/// - Throws: An SVGParserError of no such file
@available(*, deprecated)
open class func parse(bundle: Bundle, path: String, ofType: String = "svg") throws -> Node {
guard let fullPath = bundle.path(forResource: path, ofType: ofType) else {
throw SVGParserError.noSuchFile(path: "\(path).\(ofType)")
}
let text = try String(contentsOfFile: fullPath, encoding: String.Encoding.utf8)
let text = try String(contentsOfFile: fullPath, encoding: .utf8)
return try SVGParser.parse(text: text)
}

/// Parse an SVG file identified by the specified name and file extension.
/// - returns: Root node of the corresponding Macaw scene.
///
/// - Parameters:
/// - path: Resource filename
/// - ofType: Type of resource file. The default is "svg"
/// - Returns: Root node of the corresponding Macaw scene.
/// - Throws: An SVGParserError of no such file
@available(*, deprecated)
open class func parse(path: String, ofType: String = "svg") throws -> Node {
return try SVGParser.parse(bundle: Bundle.main, path: path, ofType: ofType)
}

/// Parse an SVG file
///
/// - Parameters:
/// - resource: Resource file name
/// - type: Type of resource file. The default is `svg`
/// - directory: Directory of given resource
/// - bundle: Bundle of given resource
/// - Returns: Root node of the corresponding Macaw scene.
/// - Throws: An SVGParserError of no such file
open class func parse(resource: String,
ofType type: String = "svg",
inDirectory directory: String? = nil,
fromBundle bundle: Bundle = Bundle.main) throws -> Node {
guard let fullpath = bundle.path(forResource: resource, ofType: type, inDirectory: directory) else {
throw SVGParserError.noSuchFile(path: "\(resource).\(type)")
}
return try SVGParser.parse(fullPath: fullpath)
}

/// Parse an SVG file identified by full file path
///
/// - Parameter fullPath: Full path
/// - Returns: Root node of the corresponding Macaw scene.
/// - Throws: An SVGParserError of no such file
open class func parse(fullPath: String) throws -> Node {
guard let text = try? String(contentsOfFile: fullPath, encoding: .utf8) else {
throw SVGParserError.noSuchFile(path: fullPath)
}
return try SVGParser.parse(text: text)
}

/// Parse the specified content of an SVG file.
/// - returns: Root node of the corresponding Macaw scene.
open class func parse(text: String) throws -> Node {
Expand Down
2 changes: 1 addition & 1 deletion Source/svg/SVGParserError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
//
//

enum SVGParserError: Error {
enum SVGParserError: Error, Equatable {
case noSuchFile(path: String)
}
2 changes: 1 addition & 1 deletion Source/svg/SVGView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ open class SVGView: MacawView {

@IBInspectable open var fileName: String? {
didSet {
node = (try? SVGParser.parse(path: fileName ?? "")) ?? Group()
node = (try? SVGParser.parse(resource: fileName ?? "")) ?? Group()
}
}

Expand Down