diff --git a/.gitignore b/.gitignore index a3cd143..cbc7673 100644 --- a/.gitignore +++ b/.gitignore @@ -1,26 +1 @@ -# Xcode -# -build/ -*.pbxuser -!default.pbxuser -*.mode1v3 -!default.mode1v3 -*.mode2v3 -!default.mode2v3 -*.perspectivev3 -!default.perspectivev3 -xcuserdata -*.xccheckout -*.moved-aside -DerivedData -*.hmap -*.ipa -*.xcuserstate - -# CocoaPods -# -# We recommend against adding the Pods directory to your .gitignore. However -# you should judge for yourself, the pros and cons are mentioned at: -# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control -# -# Pods/ +.conche/ diff --git a/Podfile b/Podfile deleted file mode 100644 index 86d002e..0000000 --- a/Podfile +++ /dev/null @@ -1,10 +0,0 @@ -use_frameworks! - -target 'Stencil' do - podspec -end - -target 'StencilTests' do - podspec -end - diff --git a/Podfile.lock b/Podfile.lock deleted file mode 100644 index 2ac8bc2..0000000 --- a/Podfile.lock +++ /dev/null @@ -1,10 +0,0 @@ -PODS: - - PathKit (0.5.0) - -DEPENDENCIES: - - PathKit (~> 0.5.0) - -SPEC CHECKSUMS: - PathKit: 64e70cb924d6faed9251049f5f28662855524baf - -COCOAPODS: 0.38.2 diff --git a/Stencil.podspec.json b/Stencil.podspec.json index 3c90b8c..df4f2c7 100644 --- a/Stencil.podspec.json +++ b/Stencil.podspec.json @@ -26,5 +26,16 @@ "requires_arc": true, "dependencies": { "PathKit": [ "~> 0.5.0" ] + }, + "test_specification": { + "source_files": [ + "StencilSpecs/*.swift", + "StencilSpecs/TemplateLoader/*.swift", + "StencilSpecs/Nodes/*.swift" + ], + "dependencies": { + "Spectre": [ "~> 0.4.1" ], + "PathKit": [ "~> 0.5.0" ] + } } } diff --git a/Stencil.xcodeproj/project.pbxproj b/Stencil.xcodeproj/project.pbxproj deleted file mode 100644 index 3dcff7b..0000000 --- a/Stencil.xcodeproj/project.pbxproj +++ /dev/null @@ -1,656 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 27A848E41B42240E004ACA13 /* Inheritence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A848E31B42240E004ACA13 /* Inheritence.swift */; }; - 27A848E91B42242C004ACA13 /* base.html in Resources */ = {isa = PBXBuildFile; fileRef = 27A848E71B42242C004ACA13 /* base.html */; }; - 27A848EA1B42242C004ACA13 /* child.html in Resources */ = {isa = PBXBuildFile; fileRef = 27A848E81B42242C004ACA13 /* child.html */; }; - 27A848EC1B42247D004ACA13 /* InheritenceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27A848EB1B42247D004ACA13 /* InheritenceTests.swift */; }; - 27BA0A9E1BD9465700B7209B /* Filters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27BA0A9D1BD9465700B7209B /* Filters.swift */; settings = {ASSET_TAGS = (); }; }; - 27BA0AA01BD946C300B7209B /* FilterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27BA0A9F1BD946C300B7209B /* FilterTests.swift */; settings = {ASSET_TAGS = (); }; }; - 27CE0ADE1A50BEC3004A105B /* TemplateLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27CE0ADD1A50BEC3004A105B /* TemplateLoader.swift */; }; - 27CE0AE01A50BF05004A105B /* TemplateLoaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27CE0ADF1A50BF05004A105B /* TemplateLoaderTests.swift */; }; - 27CE0AFA1A50C963004A105B /* test.html in Resources */ = {isa = PBXBuildFile; fileRef = 27CE0AF91A50C963004A105B /* test.html */; }; - 27CE0B011A50CBD1004A105B /* Include.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27CE0B001A50CBD1004A105B /* Include.swift */; }; - 27CE0B041A50CBEA004A105B /* IncludeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27CE0B031A50CBEA004A105B /* IncludeTests.swift */; }; - 7725B3CB19F92B4F002CF74B /* VariableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7725B3CA19F92B4F002CF74B /* VariableTests.swift */; }; - 7725B3CD19F92B61002CF74B /* Variable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7725B3CC19F92B61002CF74B /* Variable.swift */; }; - 7725B3CF19F94214002CF74B /* Tokenizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7725B3CE19F94214002CF74B /* Tokenizer.swift */; }; - 7725B3D319F9437F002CF74B /* NodeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7725B3D219F9437F002CF74B /* NodeTests.swift */; }; - 7725B3D519F9438F002CF74B /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7725B3D419F9438F002CF74B /* Node.swift */; }; - 7725B3D719F94A43002CF74B /* Parser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7725B3D619F94A43002CF74B /* Parser.swift */; }; - 7725B3D919F94A61002CF74B /* ParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7725B3D819F94A61002CF74B /* ParserTests.swift */; }; - 77EB082519F96E88001870F1 /* Template.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77EB082419F96E88001870F1 /* Template.swift */; }; - 77EB082719F96E9C001870F1 /* TemplateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77EB082619F96E9C001870F1 /* TemplateTests.swift */; }; - 77EB082919FA85F2001870F1 /* LexerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77EB082819FA85F2001870F1 /* LexerTests.swift */; }; - 77EB082B19FA8600001870F1 /* Lexer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77EB082A19FA8600001870F1 /* Lexer.swift */; }; - 77FAAE5819F91E480029DC5E /* Stencil.h in Headers */ = {isa = PBXBuildFile; fileRef = 77FAAE5719F91E480029DC5E /* Stencil.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 77FAAE5E19F91E480029DC5E /* Stencil.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77FAAE5219F91E480029DC5E /* Stencil.framework */; }; - 77FAAE6519F91E480029DC5E /* StencilTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FAAE6419F91E480029DC5E /* StencilTests.swift */; }; - 77FAAE6F19F920750029DC5E /* Context.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FAAE6E19F920750029DC5E /* Context.swift */; }; - 77FAAE7119F9208C0029DC5E /* ContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77FAAE7019F9208C0029DC5E /* ContextTests.swift */; }; - B47F77A0E91D074331ECA4BA /* Pods_StencilTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 993D1013A77A01814D8E4A04 /* Pods_StencilTests.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; - EE07225918EA237F21D8B902 /* Pods_Stencil.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 19D2CE595625A4F7A865B0BD /* Pods_Stencil.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 27CE0AF51A50C292004A105B /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 77FAAE4919F91E480029DC5E /* Project object */; - proxyType = 1; - remoteGlobalIDString = 77FAAE5119F91E480029DC5E; - remoteInfo = Stencil; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 19D2CE595625A4F7A865B0BD /* Pods_Stencil.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Stencil.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 1F9D5A26B78DADAECC18CA94 /* Pods-Stencil.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Stencil.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Stencil/Pods-Stencil.debug.xcconfig"; sourceTree = ""; }; - 27A848E31B42240E004ACA13 /* Inheritence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Inheritence.swift; sourceTree = ""; }; - 27A848E71B42242C004ACA13 /* base.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = base.html; sourceTree = ""; }; - 27A848E81B42242C004ACA13 /* child.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = child.html; sourceTree = ""; }; - 27A848EB1B42247D004ACA13 /* InheritenceTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InheritenceTests.swift; sourceTree = ""; }; - 27BA0A9D1BD9465700B7209B /* Filters.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Filters.swift; sourceTree = ""; }; - 27BA0A9F1BD946C300B7209B /* FilterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FilterTests.swift; sourceTree = ""; }; - 27CE0ADD1A50BEC3004A105B /* TemplateLoader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TemplateLoader.swift; sourceTree = ""; }; - 27CE0ADF1A50BF05004A105B /* TemplateLoaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TemplateLoaderTests.swift; sourceTree = ""; }; - 27CE0AF91A50C963004A105B /* test.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = test.html; sourceTree = ""; }; - 27CE0B001A50CBD1004A105B /* Include.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Include.swift; sourceTree = ""; }; - 27CE0B031A50CBEA004A105B /* IncludeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IncludeTests.swift; sourceTree = ""; }; - 7725B3CA19F92B4F002CF74B /* VariableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VariableTests.swift; sourceTree = ""; }; - 7725B3CC19F92B61002CF74B /* Variable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Variable.swift; sourceTree = ""; }; - 7725B3CE19F94214002CF74B /* Tokenizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Tokenizer.swift; sourceTree = ""; }; - 7725B3D219F9437F002CF74B /* NodeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NodeTests.swift; sourceTree = ""; }; - 7725B3D419F9438F002CF74B /* Node.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Node.swift; sourceTree = ""; }; - 7725B3D619F94A43002CF74B /* Parser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Parser.swift; sourceTree = ""; }; - 7725B3D819F94A61002CF74B /* ParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ParserTests.swift; sourceTree = ""; }; - 77EB082419F96E88001870F1 /* Template.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Template.swift; sourceTree = ""; }; - 77EB082619F96E9C001870F1 /* TemplateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TemplateTests.swift; sourceTree = ""; }; - 77EB082819FA85F2001870F1 /* LexerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LexerTests.swift; sourceTree = ""; }; - 77EB082A19FA8600001870F1 /* Lexer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Lexer.swift; sourceTree = ""; }; - 77FAAE5219F91E480029DC5E /* Stencil.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Stencil.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 77FAAE5619F91E480029DC5E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 77FAAE5719F91E480029DC5E /* Stencil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Stencil.h; sourceTree = ""; }; - 77FAAE5D19F91E480029DC5E /* StencilTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StencilTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 77FAAE6319F91E480029DC5E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 77FAAE6419F91E480029DC5E /* StencilTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StencilTests.swift; sourceTree = ""; }; - 77FAAE6E19F920750029DC5E /* Context.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Context.swift; sourceTree = ""; }; - 77FAAE7019F9208C0029DC5E /* ContextTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContextTests.swift; sourceTree = ""; }; - 8E90EE157CBB4F8E96884DED /* Pods-Stencil.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Stencil.release.xcconfig"; path = "Pods/Target Support Files/Pods-Stencil/Pods-Stencil.release.xcconfig"; sourceTree = ""; }; - 993D1013A77A01814D8E4A04 /* Pods_StencilTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_StencilTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D504530B9669DDF40C6890DF /* Pods-StencilTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StencilTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-StencilTests/Pods-StencilTests.release.xcconfig"; sourceTree = ""; }; - D7B326C5BB2955F522787D9B /* Pods-StencilTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-StencilTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-StencilTests/Pods-StencilTests.debug.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 77FAAE4E19F91E480029DC5E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - EE07225918EA237F21D8B902 /* Pods_Stencil.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 77FAAE5A19F91E480029DC5E /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 77FAAE5E19F91E480029DC5E /* Stencil.framework in Frameworks */, - B47F77A0E91D074331ECA4BA /* Pods_StencilTests.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 27CE0AFF1A50CBBF004A105B /* TemplateLoader */ = { - isa = PBXGroup; - children = ( - 27CE0B001A50CBD1004A105B /* Include.swift */, - 27A848E31B42240E004ACA13 /* Inheritence.swift */, - ); - path = TemplateLoader; - sourceTree = ""; - }; - 27CE0B021A50CBEA004A105B /* TemplateLoader */ = { - isa = PBXGroup; - children = ( - 27CE0B031A50CBEA004A105B /* IncludeTests.swift */, - 27A848EB1B42247D004ACA13 /* InheritenceTests.swift */, - ); - path = TemplateLoader; - sourceTree = ""; - }; - 77FAAE4819F91E480029DC5E = { - isa = PBXGroup; - children = ( - 77FAAE5419F91E480029DC5E /* Stencil */, - 77FAAE6119F91E480029DC5E /* StencilTests */, - 77FAAE5319F91E480029DC5E /* Products */, - C06534353970612CB8F9960D /* Pods */, - A82CB85756DE155E072D4047 /* Frameworks */, - ); - indentWidth = 2; - sourceTree = ""; - tabWidth = 2; - }; - 77FAAE5319F91E480029DC5E /* Products */ = { - isa = PBXGroup; - children = ( - 77FAAE5219F91E480029DC5E /* Stencil.framework */, - 77FAAE5D19F91E480029DC5E /* StencilTests.xctest */, - ); - name = Products; - sourceTree = ""; - }; - 77FAAE5419F91E480029DC5E /* Stencil */ = { - isa = PBXGroup; - children = ( - 77FAAE5719F91E480029DC5E /* Stencil.h */, - 77FAAE6E19F920750029DC5E /* Context.swift */, - 27BA0A9D1BD9465700B7209B /* Filters.swift */, - 77EB082A19FA8600001870F1 /* Lexer.swift */, - 7725B3D419F9438F002CF74B /* Node.swift */, - 7725B3D619F94A43002CF74B /* Parser.swift */, - 77EB082419F96E88001870F1 /* Template.swift */, - 27CE0ADD1A50BEC3004A105B /* TemplateLoader.swift */, - 7725B3CE19F94214002CF74B /* Tokenizer.swift */, - 7725B3CC19F92B61002CF74B /* Variable.swift */, - 27CE0AFF1A50CBBF004A105B /* TemplateLoader */, - 77FAAE5519F91E480029DC5E /* Supporting Files */, - ); - path = Stencil; - sourceTree = ""; - }; - 77FAAE5519F91E480029DC5E /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 77FAAE5619F91E480029DC5E /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 77FAAE6119F91E480029DC5E /* StencilTests */ = { - isa = PBXGroup; - children = ( - 77FAAE6419F91E480029DC5E /* StencilTests.swift */, - 77FAAE7019F9208C0029DC5E /* ContextTests.swift */, - 7725B3CA19F92B4F002CF74B /* VariableTests.swift */, - 7725B3D219F9437F002CF74B /* NodeTests.swift */, - 27BA0A9F1BD946C300B7209B /* FilterTests.swift */, - 7725B3D819F94A61002CF74B /* ParserTests.swift */, - 77EB082819FA85F2001870F1 /* LexerTests.swift */, - 77EB082619F96E9C001870F1 /* TemplateTests.swift */, - 27CE0ADF1A50BF05004A105B /* TemplateLoaderTests.swift */, - 27CE0B021A50CBEA004A105B /* TemplateLoader */, - 27CE0AF91A50C963004A105B /* test.html */, - 27A848E71B42242C004ACA13 /* base.html */, - 27A848E81B42242C004ACA13 /* child.html */, - 77FAAE6219F91E480029DC5E /* Supporting Files */, - ); - path = StencilTests; - sourceTree = ""; - }; - 77FAAE6219F91E480029DC5E /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 77FAAE6319F91E480029DC5E /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - A82CB85756DE155E072D4047 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 19D2CE595625A4F7A865B0BD /* Pods_Stencil.framework */, - 993D1013A77A01814D8E4A04 /* Pods_StencilTests.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - C06534353970612CB8F9960D /* Pods */ = { - isa = PBXGroup; - children = ( - 1F9D5A26B78DADAECC18CA94 /* Pods-Stencil.debug.xcconfig */, - 8E90EE157CBB4F8E96884DED /* Pods-Stencil.release.xcconfig */, - D7B326C5BB2955F522787D9B /* Pods-StencilTests.debug.xcconfig */, - D504530B9669DDF40C6890DF /* Pods-StencilTests.release.xcconfig */, - ); - name = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 77FAAE4F19F91E480029DC5E /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 77FAAE5819F91E480029DC5E /* Stencil.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 77FAAE5119F91E480029DC5E /* Stencil */ = { - isa = PBXNativeTarget; - buildConfigurationList = 77FAAE6819F91E480029DC5E /* Build configuration list for PBXNativeTarget "Stencil" */; - buildPhases = ( - AFE0827734C5388F8E996172 /* Check Pods Manifest.lock */, - 77FAAE4D19F91E480029DC5E /* Sources */, - 77FAAE4E19F91E480029DC5E /* Frameworks */, - 77FAAE4F19F91E480029DC5E /* Headers */, - 77FAAE5019F91E480029DC5E /* Resources */, - 5374160581EF83B2213B72F1 /* Copy Pods Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Stencil; - productName = Stencil; - productReference = 77FAAE5219F91E480029DC5E /* Stencil.framework */; - productType = "com.apple.product-type.framework"; - }; - 77FAAE5C19F91E480029DC5E /* StencilTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 77FAAE6B19F91E480029DC5E /* Build configuration list for PBXNativeTarget "StencilTests" */; - buildPhases = ( - C50FF01A96AD1CEACBF2E02A /* Check Pods Manifest.lock */, - 77FAAE5919F91E480029DC5E /* Sources */, - 77FAAE5A19F91E480029DC5E /* Frameworks */, - 77FAAE5B19F91E480029DC5E /* Resources */, - 138C1DDF1FB55A83668EE384 /* Embed Pods Frameworks */, - 36A8E92EBDE6D917075028D4 /* Copy Pods Resources */, - ); - buildRules = ( - ); - dependencies = ( - 27CE0AF61A50C292004A105B /* PBXTargetDependency */, - ); - name = StencilTests; - productName = StencilTests; - productReference = 77FAAE5D19F91E480029DC5E /* StencilTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 77FAAE4919F91E480029DC5E /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0700; - ORGANIZATIONNAME = Cocode; - TargetAttributes = { - 77FAAE5119F91E480029DC5E = { - CreatedOnToolsVersion = 6.1; - }; - 77FAAE5C19F91E480029DC5E = { - CreatedOnToolsVersion = 6.1; - }; - }; - }; - buildConfigurationList = 77FAAE4C19F91E480029DC5E /* Build configuration list for PBXProject "Stencil" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 77FAAE4819F91E480029DC5E; - productRefGroup = 77FAAE5319F91E480029DC5E /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 77FAAE5119F91E480029DC5E /* Stencil */, - 77FAAE5C19F91E480029DC5E /* StencilTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 77FAAE5019F91E480029DC5E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 77FAAE5B19F91E480029DC5E /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 27CE0AFA1A50C963004A105B /* test.html in Resources */, - 27A848EA1B42242C004ACA13 /* child.html in Resources */, - 27A848E91B42242C004ACA13 /* base.html in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 138C1DDF1FB55A83668EE384 /* Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Embed Pods Frameworks"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-StencilTests/Pods-StencilTests-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 36A8E92EBDE6D917075028D4 /* Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-StencilTests/Pods-StencilTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - 5374160581EF83B2213B72F1 /* Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Stencil/Pods-Stencil-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - AFE0827734C5388F8E996172 /* Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Check Pods Manifest.lock"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; - C50FF01A96AD1CEACBF2E02A /* Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Check Pods Manifest.lock"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 77FAAE4D19F91E480029DC5E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 27CE0B011A50CBD1004A105B /* Include.swift in Sources */, - 77FAAE6F19F920750029DC5E /* Context.swift in Sources */, - 77EB082B19FA8600001870F1 /* Lexer.swift in Sources */, - 7725B3CF19F94214002CF74B /* Tokenizer.swift in Sources */, - 27BA0A9E1BD9465700B7209B /* Filters.swift in Sources */, - 7725B3D719F94A43002CF74B /* Parser.swift in Sources */, - 77EB082519F96E88001870F1 /* Template.swift in Sources */, - 7725B3CD19F92B61002CF74B /* Variable.swift in Sources */, - 7725B3D519F9438F002CF74B /* Node.swift in Sources */, - 27CE0ADE1A50BEC3004A105B /* TemplateLoader.swift in Sources */, - 27A848E41B42240E004ACA13 /* Inheritence.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 77FAAE5919F91E480029DC5E /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 77FAAE6519F91E480029DC5E /* StencilTests.swift in Sources */, - 7725B3D319F9437F002CF74B /* NodeTests.swift in Sources */, - 27A848EC1B42247D004ACA13 /* InheritenceTests.swift in Sources */, - 27CE0AE01A50BF05004A105B /* TemplateLoaderTests.swift in Sources */, - 7725B3D919F94A61002CF74B /* ParserTests.swift in Sources */, - 77EB082719F96E9C001870F1 /* TemplateTests.swift in Sources */, - 7725B3CB19F92B4F002CF74B /* VariableTests.swift in Sources */, - 27CE0B041A50CBEA004A105B /* IncludeTests.swift in Sources */, - 27BA0AA01BD946C300B7209B /* FilterTests.swift in Sources */, - 77EB082919FA85F2001870F1 /* LexerTests.swift in Sources */, - 77FAAE7119F9208C0029DC5E /* ContextTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 27CE0AF61A50C292004A105B /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 77FAAE5119F91E480029DC5E /* Stencil */; - targetProxy = 27CE0AF51A50C292004A105B /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 77FAAE6619F91E480029DC5E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - CURRENT_PROJECT_VERSION = 1; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 77FAAE6719F91E480029DC5E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.9; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = macosx; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - 77FAAE6919F91E480029DC5E /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1F9D5A26B78DADAECC18CA94 /* Pods-Stencil.debug.xcconfig */; - buildSettings = { - CLANG_ENABLE_MODULES = YES; - COMBINE_HIDPI_IMAGES = YES; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_VERSION = A; - INFOPLIST_FILE = Stencil/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 77FAAE6A19F91E480029DC5E /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8E90EE157CBB4F8E96884DED /* Pods-Stencil.release.xcconfig */; - buildSettings = { - CLANG_ENABLE_MODULES = YES; - COMBINE_HIDPI_IMAGES = YES; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - FRAMEWORK_VERSION = A; - INFOPLIST_FILE = Stencil/Info.plist; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - }; - name = Release; - }; - 77FAAE6C19F91E480029DC5E /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = D7B326C5BB2955F522787D9B /* Pods-StencilTests.debug.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(DEVELOPER_FRAMEWORKS_DIR)", - "$(inherited)", - ); - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = StencilTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 77FAAE6D19F91E480029DC5E /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = D504530B9669DDF40C6890DF /* Pods-StencilTests.release.xcconfig */; - buildSettings = { - COMBINE_HIDPI_IMAGES = YES; - FRAMEWORK_SEARCH_PATHS = ( - "$(DEVELOPER_FRAMEWORKS_DIR)", - "$(inherited)", - ); - INFOPLIST_FILE = StencilTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocode.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 77FAAE4C19F91E480029DC5E /* Build configuration list for PBXProject "Stencil" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 77FAAE6619F91E480029DC5E /* Debug */, - 77FAAE6719F91E480029DC5E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 77FAAE6819F91E480029DC5E /* Build configuration list for PBXNativeTarget "Stencil" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 77FAAE6919F91E480029DC5E /* Debug */, - 77FAAE6A19F91E480029DC5E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 77FAAE6B19F91E480029DC5E /* Build configuration list for PBXNativeTarget "StencilTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 77FAAE6C19F91E480029DC5E /* Debug */, - 77FAAE6D19F91E480029DC5E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 77FAAE4919F91E480029DC5E /* Project object */; -} diff --git a/Stencil.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Stencil.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 1533932..0000000 --- a/Stencil.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Stencil.xcodeproj/xcshareddata/xcschemes/Stencil.xcscheme b/Stencil.xcodeproj/xcshareddata/xcschemes/Stencil.xcscheme deleted file mode 100644 index a3bfad0..0000000 --- a/Stencil.xcodeproj/xcshareddata/xcschemes/Stencil.xcscheme +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Stencil.xcworkspace/contents.xcworkspacedata b/Stencil.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 3505910..0000000 --- a/Stencil.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/StencilSpecs/ContextSpec.swift b/StencilSpecs/ContextSpec.swift new file mode 100644 index 0000000..d16d01f --- /dev/null +++ b/StencilSpecs/ContextSpec.swift @@ -0,0 +1,53 @@ +import Spectre +import Stencil + + +describe("Context") { + var context: Context! + + $0.before { + context = Context(dictionary: ["name": "Kyle"]) + } + + $0.it("allows you to get a value via subscripting") { + try expect(context["name"] as? String) == "Kyle" + } + + $0.it("allows you to set a value via subscripting") { + context["name"] = "Katie" + + try expect(context["name"] as? String) == "Katie" + } + + $0.it("allows you to remove a value via subscripting") { + context["name"] = nil + + try expect(context["name"]).to.beNil() + } + + $0.it("allows you to retrieve a value from a parent") { + context.push() + + try expect(context["name"] as? String) == "Kyle" + } + + $0.it("allows you to override a parent's value") { + context.push() + context["name"] = "Katie" + + try expect(context["name"] as? String) == "Katie" + } + + $0.it("allows you to pop to restore previous state") { + context.push() + context["name"] = "Katie" + context.pop() + + try expect(context["name"] as? String) == "Kyle" + } + + $0.it("allows you to push a dictionary onto the stack") { + context.push(["name": "Katie"]) + try expect(context["name"] as? String) == "Katie" + } +} diff --git a/StencilSpecs/FilterSpec.swift b/StencilSpecs/FilterSpec.swift new file mode 100644 index 0000000..8fa099d --- /dev/null +++ b/StencilSpecs/FilterSpec.swift @@ -0,0 +1,30 @@ +import Spectre +import Stencil + + +describe("capitalize filter") { + let template = Template(templateString: "{{ name|capitalize }}") + + $0.it("capitalizes a string") { + let result = try template.render(Context(dictionary: ["name": "kyle"])) + try expect(result) == "Kyle" + } +} + +describe("uppercase filter") { + let template = Template(templateString: "{{ name|uppercase }}") + + $0.it("transforms a string to be uppercase") { + let result = try template.render(Context(dictionary: ["name": "kyle"])) + try expect(result) == "KYLE" + } +} + +describe("lowercase filter") { + let template = Template(templateString: "{{ name|lowercase }}") + + $0.it("transforms a string to be lowercase") { + let result = try template.render(Context(dictionary: ["name": "Kyle"])) + try expect(result) == "kyle" + } +} diff --git a/StencilSpecs/LexerSpec.swift b/StencilSpecs/LexerSpec.swift new file mode 100644 index 0000000..c31f876 --- /dev/null +++ b/StencilSpecs/LexerSpec.swift @@ -0,0 +1,48 @@ +import Spectre +import Stencil + + +describe("Lexer") { + $0.it("can tokenize text") { + let lexer = Lexer(templateString: "Hello World") + let tokens = lexer.tokenize() + + try expect(tokens.count) == 1 + try expect(tokens.first) == Token.Text(value: "Hello World") + } + + $0.it("can tokenize a comment") { + let lexer = Lexer(templateString: "{# Comment #}") + let tokens = lexer.tokenize() + + try expect(tokens.count) == (1) + try expect(tokens.first) == Token.Comment(value: "Comment") + } + + $0.it("can tokenize a variable") { + let lexer = Lexer(templateString: "{{ Variable }}") + let tokens = lexer.tokenize() + + try expect(tokens.count) == 1 + try expect(tokens.first) == Token.Variable(value: "Variable") + } + + $0.it("can tokenize a mixture of content") { + let lexer = Lexer(templateString: "My name is {{ name }}.") + let tokens = lexer.tokenize() + + try expect(tokens.count) == 3 + try expect(tokens[0]) == Token.Text(value: "My name is ") + try expect(tokens[1]) == Token.Variable(value: "name") + try expect(tokens[2]) == Token.Text(value: ".") + } + + $0.it("can tokenize two variables without being greedy") { + let lexer = Lexer(templateString: "{{ thing }}{{ name }}") + let tokens = lexer.tokenize() + + try expect(tokens.count) == 2 + try expect(tokens[0]) == Token.Variable(value: "thing") + try expect(tokens[1]) == Token.Variable(value: "name") + } +} diff --git a/StencilSpecs/Nodes/IfNodeSpec.swift b/StencilSpecs/Nodes/IfNodeSpec.swift new file mode 100644 index 0000000..09e49b9 --- /dev/null +++ b/StencilSpecs/Nodes/IfNodeSpec.swift @@ -0,0 +1,86 @@ +import Spectre +import Stencil + +describe("IfNode") { + $0.describe("parsing") { + $0.it("can parse an if block") { + let tokens = [ + Token.Block(value: "if value"), + Token.Text(value: "true"), + Token.Block(value: "else"), + Token.Text(value: "false"), + Token.Block(value: "endif") + ] + + let parser = TokenParser(tokens: tokens) + let nodes = try parser.parse() + let node = nodes.first as? IfNode + let trueNode = node?.trueNodes.first as? TextNode + let falseNode = node?.falseNodes.first as? TextNode + + try expect(nodes.count) == 1 + try expect(node?.variable.variable) == "value" + try expect(node?.trueNodes.count) == 1 + try expect(trueNode?.text) == "true" + try expect(node?.falseNodes.count) == 1 + try expect(falseNode?.text) == "false" + } + + $0.it("can parse an ifnot block") { + let tokens = [ + Token.Block(value: "ifnot value"), + Token.Text(value: "false"), + Token.Block(value: "else"), + Token.Text(value: "true"), + Token.Block(value: "endif") + ] + + let parser = TokenParser(tokens: tokens) + let nodes = try parser.parse() + let node = nodes.first as? IfNode + let trueNode = node?.trueNodes.first as? TextNode + let falseNode = node?.falseNodes.first as? TextNode + + try expect(nodes.count) == 1 + try expect(node?.variable.variable) == "value" + try expect(node?.trueNodes.count) == 1 + try expect(trueNode?.text) == "true" + try expect(node?.falseNodes.count) == 1 + try expect(falseNode?.text) == "false" + } + + $0.it("throws an error when parsing an if block without an endif") { + let tokens = [ + Token.Block(value: "if value"), + ] + + let parser = TokenParser(tokens: tokens) + let error = TemplateSyntaxError("`endif` was not found.") + try expect(try parser.parse()).toThrow(error) + } + + $0.it("throws an error when parsing an ifnot without an endif") { + let tokens = [ + Token.Block(value: "ifnot value"), + ] + + let parser = TokenParser(tokens: tokens) + let error = TemplateSyntaxError("`endif` was not found.") + try expect(try parser.parse()).toThrow(error) + } + } + + $0.describe("rendering") { + let context = Context(dictionary: ["items": true]) + + $0.it("renders the truth when expression evaluates to true") { + let node = IfNode(variable: "items", trueNodes: [TextNode(text: "true")], falseNodes: [TextNode(text: "false")]) + try expect(try node.render(context)) == "true" + } + + $0.it("renders the false when expression evaluates to false") { + let node = IfNode(variable: "unknown", trueNodes: [TextNode(text: "true")], falseNodes: [TextNode(text: "false")]) + try expect(try node.render(context)) == "false" + } + } +} diff --git a/StencilSpecs/Nodes/NodeSpec.swift b/StencilSpecs/Nodes/NodeSpec.swift new file mode 100644 index 0000000..3c4dd6f --- /dev/null +++ b/StencilSpecs/Nodes/NodeSpec.swift @@ -0,0 +1,66 @@ +import Spectre +import Stencil + + +class ErrorNode : NodeType { + func render(context: Context) throws -> String { + throw TemplateSyntaxError("Custom Error") + } +} + + +describe("Node") { + let context = Context(dictionary: [ + "name": "Kyle", + "age": 27, + "items": [1, 2, 3], + ]) + + $0.describe("TextNode") { + $0.it("renders the given text") { + let node = TextNode(text: "Hello World") + try expect(try node.render(context)) == "Hello World" + } + } + + $0.describe("VariableNode") { + $0.it("resolves and renders the variable") { + let node = VariableNode(variable: Variable("name")) + try expect(try node.render(context)) == "Kyle" + } + + $0.it("resolves and renders a non string variable") { + let node = VariableNode(variable: Variable("age")) + try expect(try node.render(context)) == "27" + } + } + + $0.describe("rendering nodes") { + $0.it("renders the nodes") { + let nodes: [NodeType] = [ + TextNode(text:"Hello "), + VariableNode(variable: "name"), + ] + + try expect(try renderNodes(nodes, context)) == "Hello Kyle" + } + + $0.it("correctly throws a nodes failure") { + let nodes: [NodeType] = [ + TextNode(text:"Hello "), + VariableNode(variable: "name"), + ErrorNode(), + ] + + try expect(try renderNodes(nodes, context)).toThrow(TemplateSyntaxError("Custom Error")) + } + } + + $0.describe("ForNode") { + $0.it("renders the given nodes for each item") { + let nodes: [NodeType] = [VariableNode(variable: "item")] + let node = ForNode(variable: "items", loopVariable: "item", nodes: nodes, emptyNodes: []) + try expect(try node.render(context)) == "123" + } + } +} diff --git a/StencilSpecs/Nodes/NowNodeSpec.swift b/StencilSpecs/Nodes/NowNodeSpec.swift new file mode 100644 index 0000000..c911e84 --- /dev/null +++ b/StencilSpecs/Nodes/NowNodeSpec.swift @@ -0,0 +1,39 @@ +import Foundation +import Spectre +import Stencil + + +describe("NowNode") { + $0.describe("parsing") { + $0.it("parses default format without any now arguments") { + let tokens = [ Token.Block(value: "now") ] + let parser = TokenParser(tokens: tokens) + + let nodes = try parser.parse() + let node = nodes.first as? NowNode + try expect(nodes.count) == 1 + try expect(node?.format.variable) == "\"yyyy-MM-dd 'at' HH:mm\"" + } + + $0.it("parses now with a format") { + let tokens = [ Token.Block(value: "now \"HH:mm\"") ] + let parser = TokenParser(tokens: tokens) + let nodes = try parser.parse() + let node = nodes.first as? NowNode + try expect(nodes.count) == 1 + try expect(node?.format.variable) == "\"HH:mm\"" + } + } + + $0.describe("rendering") { + $0.it("renders the date") { + let node = NowNode(format: Variable("\"yyyy-MM-dd\"")) + + let formatter = NSDateFormatter() + formatter.dateFormat = "yyyy-MM-dd" + let date = formatter.stringFromDate(NSDate()) + + try expect(try node.render(Context())) == date + } + } +} diff --git a/StencilSpecs/ParserSpec.swift b/StencilSpecs/ParserSpec.swift new file mode 100644 index 0000000..dfe59ea --- /dev/null +++ b/StencilSpecs/ParserSpec.swift @@ -0,0 +1,47 @@ +import Spectre +import Stencil + + +describe("TokenParser") { + $0.it("can parse a text token") { + let parser = TokenParser(tokens: [ + Token.Text(value: "Hello World") + ]) + + let nodes = try parser.parse() + let node = nodes.first as? TextNode + + try expect(nodes.count) == 1 + try expect(node?.text) == "Hello World" + } + + $0.it("can parse a variable token") { + let parser = TokenParser(tokens: [ + Token.Variable(value: "'name'") + ]) + + let nodes = try parser.parse() + let node = nodes.first as? VariableNode + try expect(nodes.count) == 1 + let result = try node?.render(Context()) + try expect(result) == "name" + } + + $0.it("can parse a comment token") { + let parser = TokenParser(tokens: [ + Token.Comment(value: "Secret stuff!") + ]) + + let nodes = try parser.parse() + try expect(nodes.count) == 0 + } + + $0.it("can parse a tag token") { + let parser = TokenParser(tokens: [ + Token.Block(value: "now"), + ]) + + let nodes = try parser.parse() + try expect(nodes.count) == 1 + } +} diff --git a/StencilTests/StencilTests.swift b/StencilSpecs/StencilSpec.swift similarity index 62% rename from StencilTests/StencilTests.swift rename to StencilSpecs/StencilSpec.swift index 3d77826..258de37 100644 --- a/StencilTests/StencilTests.swift +++ b/StencilSpecs/StencilSpec.swift @@ -1,24 +1,6 @@ -import Foundation -import XCTest +import Spectre import Stencil -func assertSuccess(@autoclosure closure:() throws -> (T), block:(T -> ())) { - do { - block(try closure()) - } catch { - XCTFail("Unexpected error \(error)") - } -} - -func assertFailure(@autoclosure closure:() throws -> (T), _ error:U) { - do { - try closure() - } catch let e as U { - XCTAssertEqual(e, error) - } catch { - XCTFail() - } -} class CustomNode : NodeType { func render(context:Context) throws -> String { @@ -26,8 +8,9 @@ class CustomNode : NodeType { } } -class StencilTests: XCTestCase { - func testReadmeExample() { + +describe("Stencil") { + $0.it("can render the README example") { let templateString = "There are {{ articles.count }} articles.\n" + "\n" + "{% for article in articles %}" + @@ -39,10 +22,10 @@ class StencilTests: XCTestCase { [ "title": "Migrating from OCUnit to XCTest", "author": "Kyle Fuller" ], [ "title": "Memory Management with ARC", "author": "Kyle Fuller" ], ] - ]) + ]) let template = Template(templateString:templateString) - let result = try? template.render(context) + let result = try template.render(context) let fixture = "There are 2 articles.\n" + "\n" + @@ -50,10 +33,10 @@ class StencilTests: XCTestCase { " - Memory Management with ARC by Kyle Fuller.\n" + "\n" - XCTAssertEqual(result, fixture) + try expect(result) == fixture } - func testCustomTag() { + $0.it("can render a custom template tag") { let templateString = "{% custom %}" let template = Template(templateString:templateString) @@ -61,10 +44,11 @@ class StencilTests: XCTestCase { return CustomNode() } - XCTAssertEqual(try? template.render(), "Hello World") + let result = try template.render() + try expect(result) == "Hello World" } - func testSimpleCustomTag() { + $0.it("can render a simple custom tag") { let templateString = "{% custom %}" let template = Template(templateString:templateString) @@ -72,6 +56,6 @@ class StencilTests: XCTestCase { return "Hello World" } - XCTAssertEqual(try? template.render(), "Hello World") + try expect(try template.render()) == "Hello World" } } diff --git a/StencilSpecs/TemplateLoader/IncludeSpec.swift b/StencilSpecs/TemplateLoader/IncludeSpec.swift new file mode 100644 index 0000000..38b0345 --- /dev/null +++ b/StencilSpecs/TemplateLoader/IncludeSpec.swift @@ -0,0 +1,58 @@ +import Spectre +import Stencil +import PathKit + + +describe("Include") { + let path = Path(__FILE__) + ".." + ".." + "StencilSpecs" + "fixtures" + let loader = TemplateLoader(paths: [path]) + + $0.describe("parsing") { + $0.it("throws an error when no template is given") { + let tokens = [ Token.Block(value: "include") ] + let parser = TokenParser(tokens: tokens) + + let error = TemplateSyntaxError("'include' tag takes one argument, the template file to be included") + try expect(try parser.parse()).toThrow(error) + } + + $0.it("can parse a valid include block") { + let tokens = [ Token.Block(value: "include \"test.html\"") ] + let parser = TokenParser(tokens: tokens) + + let nodes = try parser.parse() + let node = nodes.first as? IncludeNode + try expect(nodes.count) == 1 + try expect(node?.templateName) == "test.html" + } + } + + $0.describe("rendering") { + $0.it("throws an error when rendering without a loader") { + let node = IncludeNode(templateName: "test.html") + + do { + try node.render(Context()) + } catch { + try expect("\(error)") == "Template loader not in context" + } + } + + $0.it("throws an error when it cannot find the included template") { + let node = IncludeNode(templateName: "unknown.html") + + do { + try node.render(Context(dictionary: ["loader": loader])) + } catch { + try expect("\(error)".hasPrefix("'unknown.html' template not found")).to.beTrue() + } + } + + $0.it("successfully renders a found included template") { + let node = IncludeNode(templateName: "test.html") + let context = Context(dictionary: ["loader":loader, "target": "World"]) + let value = try node.render(context) + try expect(value) == "Hello World!" + } + } +} diff --git a/StencilSpecs/TemplateLoader/InheritenceSpec.swift b/StencilSpecs/TemplateLoader/InheritenceSpec.swift new file mode 100644 index 0000000..4c098f0 --- /dev/null +++ b/StencilSpecs/TemplateLoader/InheritenceSpec.swift @@ -0,0 +1,15 @@ +import Spectre +import Stencil +import PathKit + + +describe("Inheritence") { + let path = Path(__FILE__) + ".." + ".." + "StencilSpecs" + "fixtures" + let loader = TemplateLoader(paths: [path]) + + $0.it("can inherit from another template") { + let context = Context(dictionary: ["loader": loader]) + let template = loader.loadTemplate("child.html") + try expect(try template?.render(context)) == "Header\nChild" + } +} diff --git a/StencilSpecs/TemplateLoaderSpec.swift b/StencilSpecs/TemplateLoaderSpec.swift new file mode 100644 index 0000000..e5cf551 --- /dev/null +++ b/StencilSpecs/TemplateLoaderSpec.swift @@ -0,0 +1,23 @@ +import Spectre +import Stencil +import PathKit + + +describe("TemplateLoader") { + let path = Path(__FILE__) + ".." + ".." + "StencilSpecs" + "fixtures" + let loader = TemplateLoader(paths: [path]) + + $0.it("returns nil when a template cannot be found") { + try expect(loader.loadTemplate("unknown.html")).to.beNil() + } + + $0.it("returns nil when an array of templates cannot be found") { + try expect(loader.loadTemplate(["unknown.html", "unknown2.html"])).to.beNil() + } + + $0.it("can load a template from a file") { + if loader.loadTemplate("test.html") == nil { + throw failure("didn't find the template") + } + } +} diff --git a/StencilSpecs/TemplateSpec.swift b/StencilSpecs/TemplateSpec.swift new file mode 100644 index 0000000..30ce57f --- /dev/null +++ b/StencilSpecs/TemplateSpec.swift @@ -0,0 +1,12 @@ +import Spectre +import Stencil + + +describe("Template") { + $0.it("can render a template from a string") { + let context = Context(dictionary: [ "name": "Kyle" ]) + let template = Template(templateString: "Hello World") + let result = try template.render(context) + try expect(result) == "Hello World" + } +} diff --git a/StencilSpecs/VariableSpec.swift b/StencilSpecs/VariableSpec.swift new file mode 100644 index 0000000..c4c9a38 --- /dev/null +++ b/StencilSpecs/VariableSpec.swift @@ -0,0 +1,68 @@ +import Foundation +import Spectre +import Stencil + + +@objc class Object : NSObject { + let title = "Hello World" +} + + +describe("Variable") { + let context = Context(dictionary: [ + "name": "Kyle", + "contacts": ["Katie", "Carlton"], + "profiles": [ + "github": "kylef", + ], + "object": Object(), + ]) + + $0.it("can resolve a string literal with double quotes") { + let variable = Variable("\"name\"") + let result = variable.resolve(context) as? String + try expect(result) == "name" + } + + $0.it("can resolve a string literal with single quotes") { + let variable = Variable("'name'") + let result = variable.resolve(context) as? String + try expect(result) == "name" + } + + $0.it("can resolve a string variable") { + let variable = Variable("name") + let result = variable.resolve(context) as? String + try expect(result) == "Kyle" + } + + $0.it("can resolve an item from a dictionary") { + let variable = Variable("profiles.github") + let result = variable.resolve(context) as? String + try expect(result) == "kylef" + } + + $0.it("can resolve an item from an array via it's index") { + let variable = Variable("contacts.0") + let result = variable.resolve(context) as? String + try expect(result) == "Katie" + } + + $0.it("can resolve the first item from an array") { + let variable = Variable("contacts.first") + let result = variable.resolve(context) as? String + try expect(result) == "Katie" + } + + $0.it("can resolve the last item from an array") { + let variable = Variable("contacts.last") + let result = variable.resolve(context) as? String + try expect(result) == "Carlton" + } + + $0.it("can resolve a value via KVO") { + let variable = Variable("object.title") + let result = variable.resolve(context) as? String + try expect(result) == "Hello World" + } +} diff --git a/StencilTests/base.html b/StencilSpecs/fixtures/base.html similarity index 100% rename from StencilTests/base.html rename to StencilSpecs/fixtures/base.html diff --git a/StencilTests/child.html b/StencilSpecs/fixtures/child.html similarity index 100% rename from StencilTests/child.html rename to StencilSpecs/fixtures/child.html diff --git a/StencilTests/test.html b/StencilSpecs/fixtures/test.html similarity index 100% rename from StencilTests/test.html rename to StencilSpecs/fixtures/test.html diff --git a/StencilTests/ContextTests.swift b/StencilTests/ContextTests.swift deleted file mode 100644 index 2204514..0000000 --- a/StencilTests/ContextTests.swift +++ /dev/null @@ -1,65 +0,0 @@ -import Foundation -import XCTest -import Stencil - -class ContextTests: XCTestCase { - var context:Context! - - override func setUp() { - context = Context(dictionary: ["name": "Kyle"]) - } - - func testItAllowsYouToRetrieveAValue() { - let name = context["name"] as! String - XCTAssertEqual(name, "Kyle") - } - - func testItAllowsYouToSetValue() { - context["name"] = "Katie" - - let name = context["name"] as! String - XCTAssertEqual(name, "Katie") - } - - func testItAllowsYouToRemoveAValue() { - context["name"] = nil - XCTAssertNil(context["name"]) - } - - func testItAllowsYouToRetrieveAValueFromParent() { - context.push() - - let name = context["name"] as! String - XCTAssertEqual(name, "Kyle") - } - - func testItAllowsYouToOverideAParentVariable() { - context.push() - context["name"] = "Katie" - - let name = context["name"] as! String - XCTAssertEqual(name, "Katie") - } - - func testShowAllowYouToPopVariablesRestoringPreviousState() { - context.push() - context["name"] = "Katie" - context.pop() - - let name = context["name"] as! String - XCTAssertEqual(name, "Kyle") - } - - func testItAllowsYouToPushADictionaryToTheStack() { - context.push(["name": "Katie"]) - - let name = context["name"] as! String - XCTAssertEqual(name, "Katie") - } - - func testItAllowsYouToCompareTwoContextsForEquality() { - let otherContext = Context(dictionary: ["name": "Kyle"]) - - XCTAssertEqual(otherContext, context) - } -} diff --git a/StencilTests/FilterTests.swift b/StencilTests/FilterTests.swift deleted file mode 100644 index e1cb918..0000000 --- a/StencilTests/FilterTests.swift +++ /dev/null @@ -1,23 +0,0 @@ -import XCTest -import Stencil - - -class FilterTests: XCTestCase { - func testCapitalizeFilter() { - let template = Template(templateString: "{{ name|capitalize }}") - let result = try? template.render(Context(dictionary: ["name": "kyle"])) - XCTAssertEqual(result, "Kyle") - } - - func testUppercaseFilter() { - let template = Template(templateString: "{{ name|uppercase }}") - let result = try? template.render(Context(dictionary: ["name": "kyle"])) - XCTAssertEqual(result, "KYLE") - } - - func testLowercaseFilter() { - let template = Template(templateString: "{{ name|lowercase }}") - let result = try? template.render(Context(dictionary: ["name": "Kyle"])) - XCTAssertEqual(result, "kyle") - } -} \ No newline at end of file diff --git a/StencilTests/Info.plist b/StencilTests/Info.plist deleted file mode 100644 index ba72822..0000000 --- a/StencilTests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/StencilTests/LexerTests.swift b/StencilTests/LexerTests.swift deleted file mode 100644 index 3298c28..0000000 --- a/StencilTests/LexerTests.swift +++ /dev/null @@ -1,50 +0,0 @@ -import Foundation -import XCTest -import Stencil - -class LexerTests: XCTestCase { - - func testTokenizeText() { - let lexer = Lexer(templateString:"Hello World") - let tokens = lexer.tokenize() - - XCTAssertEqual(tokens.count, 1) - XCTAssertEqual(tokens.first!, Token.Text(value: "Hello World")) - } - - func testTokenizeComment() { - let lexer = Lexer(templateString:"{# Comment #}") - let tokens = lexer.tokenize() - - XCTAssertEqual(tokens.count, 1) - XCTAssertEqual(tokens.first!, Token.Comment(value: "Comment")) - } - - func testTokenizeVariable() { - let lexer = Lexer(templateString:"{{ Variable }}") - let tokens = lexer.tokenize() - - XCTAssertEqual(tokens.count, 1) - XCTAssertEqual(tokens.first!, Token.Variable(value: "Variable")) - } - - func testTokenizeMixture() { - let lexer = Lexer(templateString:"My name is {{ name }}.") - let tokens = lexer.tokenize() - - XCTAssertEqual(tokens.count, 3) - XCTAssertEqual(tokens[0], Token.Text(value: "My name is ")) - XCTAssertEqual(tokens[1], Token.Variable(value: "name")) - XCTAssertEqual(tokens[2], Token.Text(value: ".")) - } - - func testTokenizeTwoVariables() { // Don't be greedy - let lexer = Lexer(templateString:"{{ thing }}{{ name }}") - let tokens = lexer.tokenize() - - XCTAssertEqual(tokens.count, 2) - XCTAssertEqual(tokens[0], Token.Variable(value: "thing")) - XCTAssertEqual(tokens[1], Token.Variable(value: "name")) - } - -} diff --git a/StencilTests/NodeTests.swift b/StencilTests/NodeTests.swift deleted file mode 100644 index 224ccec..0000000 --- a/StencilTests/NodeTests.swift +++ /dev/null @@ -1,184 +0,0 @@ -import Foundation -import XCTest -import Stencil - - -class ErrorNode : NodeType { - func render(context: Context) throws -> String { - throw TemplateSyntaxError("Custom Error") - } -} - -class NodeTests: XCTestCase { - var context:Context! - - override func setUp() { - context = Context(dictionary: [ - "name": "Kyle", - "age": 27, - "items": [1,2,3], - ]) - } -} - -class TextNodeTests: NodeTests { - func testTextNodeResolvesText() { - let node = TextNode(text:"Hello World") - XCTAssertEqual(try? node.render(context), "Hello World") - } -} - -class VariableNodeTests: NodeTests { - func testVariableNodeResolvesVariable() { - let node = VariableNode(variable:Variable("name")) - XCTAssertEqual(try? node.render(context), "Kyle") - } - - func testVariableNodeResolvesNonStringVariable() { - let node = VariableNode(variable:Variable("age")) - XCTAssertEqual(try? node.render(context), "27") - } -} - -class RenderNodeTests: NodeTests { - func testRenderingNodes() { - let nodes = [TextNode(text:"Hello "), VariableNode(variable: "name")] as [NodeType] - XCTAssertEqual(try? renderNodes(nodes, context), "Hello Kyle") - } - - func testRenderingNodesWithFailure() { - let nodes = [TextNode(text:"Hello "), VariableNode(variable: "name"), ErrorNode()] as [NodeType] - - assertFailure(try renderNodes(nodes, context), TemplateSyntaxError("Custom Error")) - } -} - -class ForNodeTests: NodeTests { - func testForNodeRender() { - let node = ForNode(variable: "items", loopVariable: "item", nodes: [VariableNode(variable: "item")], emptyNodes:[]) - XCTAssertEqual(try? node.render(context), "123") - } -} - -class IfNodeTests: NodeTests { - - // MARK: Parsing - - func testParseIf() { - let tokens = [ - Token.Block(value: "if value"), - Token.Text(value: "true"), - Token.Block(value: "else"), - Token.Text(value: "false"), - Token.Block(value: "endif") - ] - - let parser = TokenParser(tokens: tokens) - assertSuccess(try parser.parse()) { nodes in - let node = nodes.first as! IfNode - let trueNode = node.trueNodes.first as! TextNode - let falseNode = node.falseNodes.first as! TextNode - - XCTAssertEqual(nodes.count, 1) - XCTAssertEqual(node.variable.variable, "value") - XCTAssertEqual(node.trueNodes.count, 1) - XCTAssertEqual(trueNode.text, "true") - XCTAssertEqual(node.falseNodes.count, 1) - XCTAssertEqual(falseNode.text, "false") - } - } - - func testParseIfNot() { - let tokens = [ - Token.Block(value: "ifnot value"), - Token.Text(value: "false"), - Token.Block(value: "else"), - Token.Text(value: "true"), - Token.Block(value: "endif") - ] - - let parser = TokenParser(tokens: tokens) - assertSuccess(try parser.parse()) { nodes in - let node = nodes.first as! IfNode - let trueNode = node.trueNodes.first as! TextNode - let falseNode = node.falseNodes.first as! TextNode - - XCTAssertEqual(nodes.count, 1) - XCTAssertEqual(node.variable.variable, "value") - XCTAssertEqual(node.trueNodes.count, 1) - XCTAssertEqual(trueNode.text, "true") - XCTAssertEqual(node.falseNodes.count, 1) - XCTAssertEqual(falseNode.text, "false") - } - } - - func testParseIfWithoutEndIfError() { - let tokens = [ - Token.Block(value: "if value"), - ] - - let parser = TokenParser(tokens: tokens) - assertFailure(try parser.parse(), TemplateSyntaxError("`endif` was not found.")) - } - - func testParseIfNotWithoutEndIfError() { - let tokens = [ - Token.Block(value: "ifnot value"), - ] - - let parser = TokenParser(tokens: tokens) - assertFailure(try parser.parse(), TemplateSyntaxError("`endif` was not found.")) - } - - // MARK: Rendering - - func testIfNodeRenderTruth() { - let node = IfNode(variable: "items", trueNodes: [TextNode(text: "true")], falseNodes: [TextNode(text: "false")]) - XCTAssertEqual(try? node.render(context), "true") - } - - func testIfNodeRenderFalse() { - let node = IfNode(variable: "unknown", trueNodes: [TextNode(text: "true")], falseNodes: [TextNode(text: "false")]) - XCTAssertEqual(try? node.render(context), "false") - } - -} - -class NowNodeTests: NodeTests { - - // MARK: Parsing - - func testParseDefaultNow() { - let tokens = [ Token.Block(value: "now") ] - let parser = TokenParser(tokens: tokens) - - assertSuccess(try parser.parse()) { nodes in - let node = nodes.first as! NowNode - XCTAssertEqual(nodes.count, 1) - XCTAssertEqual(node.format.variable, "\"yyyy-MM-dd 'at' HH:mm\"") - } - } - - func testParseNowWithFormat() { - let tokens = [ Token.Block(value: "now \"HH:mm\"") ] - let parser = TokenParser(tokens: tokens) - - assertSuccess(try parser.parse()) { nodes in - let node = nodes.first as! NowNode - XCTAssertEqual(nodes.count, 1) - XCTAssertEqual(node.format.variable, "\"HH:mm\"") - } - } - - // MARK: Rendering - - func testRenderNowNode() { - let node = NowNode(format: Variable("\"yyyy-MM-dd\"")) - - let formatter = NSDateFormatter() - formatter.dateFormat = "yyyy-MM-dd" - let date = formatter.stringFromDate(NSDate()) - - XCTAssertEqual(try? node.render(context), date) - } -} diff --git a/StencilTests/ParserTests.swift b/StencilTests/ParserTests.swift deleted file mode 100644 index ff4c83c..0000000 --- a/StencilTests/ParserTests.swift +++ /dev/null @@ -1,50 +0,0 @@ -import Foundation -import XCTest -import Stencil - -class TokenParserTests: XCTestCase { - func testParsingTextToken() { - let parser = TokenParser(tokens: [ - Token.Text(value: "Hello World") - ]) - - assertSuccess(try parser.parse()) { nodes in - let node = nodes.first as! TextNode - XCTAssertEqual(nodes.count, 1) - XCTAssertEqual(node.text, "Hello World") - } - } - - func testParsingVariableToken() { - let parser = TokenParser(tokens: [ - Token.Variable(value: "'name'") - ]) - - assertSuccess(try parser.parse()) { nodes in - let node = nodes.first as! VariableNode - XCTAssertEqual(nodes.count, 1) - let result = try? node.render(Context()) - XCTAssertEqual(result, "name") - } - } - - func testParsingCommentToken() { - let parser = TokenParser(tokens: [ - Token.Comment(value: "Secret stuff!") - ]) - - assertSuccess(try parser.parse()) { nodes in - XCTAssertEqual(nodes.count, 0) - } - } - - func testParsingTagToken() { - let parser = TokenParser(tokens: [ - Token.Block(value: "now"), - ]) - - assertSuccess(try parser.parse()) { nodes in - XCTAssertEqual(nodes.count, 1) - } - } -} diff --git a/StencilTests/TemplateLoader/IncludeTests.swift b/StencilTests/TemplateLoader/IncludeTests.swift deleted file mode 100644 index 3e84388..0000000 --- a/StencilTests/TemplateLoader/IncludeTests.swift +++ /dev/null @@ -1,64 +0,0 @@ -import Foundation -import XCTest -import Stencil -import PathKit - -class IncludeTests: NodeTests { - - var loader:TemplateLoader! - - override func setUp() { - super.setUp() - - let path = (Path(__FILE__) + Path("../..")).absolute() - loader = TemplateLoader(paths: [path]) - } - - // MARK: Parsing - - func testParseMissingTemplate() { - let tokens = [ Token.Block(value: "include") ] - let parser = TokenParser(tokens: tokens) - - assertFailure(try parser.parse(), TemplateSyntaxError("'include' tag takes one argument, the template file to be included")) - } - - func testParse() { - let tokens = [ Token.Block(value: "include \"test.html\"") ] - let parser = TokenParser(tokens: tokens) - - assertSuccess(try parser.parse()) { nodes in - let node = nodes.first as! IncludeNode - XCTAssertEqual(nodes.count, 1) - XCTAssertEqual(node.templateName, "test.html") - } - } - - // MARK: Render - - func testRenderWithoutLoader() { - let node = IncludeNode(templateName: "test.html") - - do { - try node.render(Context()) - } catch { - XCTAssertEqual("\(error)", "Template loader not in context") - } - } - - func testRenderWithoutTemplateNamed() { - let node = IncludeNode(templateName: "unknown.html") - - do { - try node.render(Context(dictionary:["loader":loader])) - } catch { - XCTAssertTrue("\(error)".hasPrefix("'unknown.html' template not found")) - } - } - - func testRender() { - let node = IncludeNode(templateName: "test.html") - let value = try? node.render(Context(dictionary:["loader":loader, "target": "World"])) - XCTAssertEqual(value, "Hello World!") - } -} diff --git a/StencilTests/TemplateLoader/InheritenceTests.swift b/StencilTests/TemplateLoader/InheritenceTests.swift deleted file mode 100644 index 306b632..0000000 --- a/StencilTests/TemplateLoader/InheritenceTests.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Foundation -import XCTest -import Stencil -import PathKit - -class InheritenceTests: NodeTests { - var loader:TemplateLoader! - - override func setUp() { - super.setUp() - - let path = (Path(__FILE__) + Path("../..")).absolute() - loader = TemplateLoader(paths: [path]) - } - - func testInheritence() { - context = Context(dictionary: ["loader": loader]) - let template = loader.loadTemplate("child.html")! - XCTAssertEqual(try? template.render(context), "Header\nChild") - } -} - -//class BlockNodeTests: NodeTests { -// func testBlockNodeWithoutChildren() { -// let context = Context() -// let block = BlockNode(name:"header", nodes:[TextNode(text: "contents")]) -// let result = block.render(context) -// -// assertSuccess(result) { rendered in -// XCTAssertEqual(rendered, "contents") -// } -// } -// -// func testBlockNodeWithChild() { -// let context = Context() -// let node = BlockNode(name:"header", nodes:[TextNode(text: "contents")]) -// let childBlock = BlockNode(name: "header", nodes: [TextNode(text: "child contents")]) -// let result = node.render(context) -// -// assertSuccess(result) { rendered in -// XCTAssertEqual(rendered, "child contents") -// } -// } -//} diff --git a/StencilTests/TemplateLoaderTests.swift b/StencilTests/TemplateLoaderTests.swift deleted file mode 100644 index da43ce5..0000000 --- a/StencilTests/TemplateLoaderTests.swift +++ /dev/null @@ -1,24 +0,0 @@ -import Foundation -import XCTest -import Stencil -import PathKit - -class TemplateLoaderTests: XCTestCase { - - func testLoadingUnknownTemplate() { - let loader = TemplateLoader(paths:[]) - XCTAssertNil(loader.loadTemplate("unknown.html")) - } - - func testLoadingUnknownTemplates() { - let loader = TemplateLoader(paths:[]) - XCTAssertNil(loader.loadTemplate(["unknown.html", "unknown2.html"])) - } - - func testLoadingTemplate() { - let path = (Path(__FILE__) + Path("..")).absolute() - let loader = TemplateLoader(paths: [path]) - XCTAssertTrue(loader.loadTemplate("test.html") != nil) - } - -} diff --git a/StencilTests/TemplateTests.swift b/StencilTests/TemplateTests.swift deleted file mode 100644 index eb37904..0000000 --- a/StencilTests/TemplateTests.swift +++ /dev/null @@ -1,40 +0,0 @@ -import Foundation -import XCTest -import Stencil - -class TemplateTests: XCTestCase { - func testTemplate() { - let context = Context(dictionary: [ "name": "Kyle" ]) - let template = Template(templateString: "Hello World") - let result = try? template.render(context) - XCTAssertEqual(result, "Hello World") - } - - func testTemplateNamedInBundle() { - let testBundle = NSBundle(forClass: self.dynamicType) - let template = try? Template(named: "test.html", inBundle: testBundle) - let context = Context(dictionary: [ "target": "Kyle" ]) - - XCTAssertNotNil(template) - let result = try? template!.render(context) - XCTAssertEqual(result, "Hello Kyle!") - } - - func testTemplateNamedInBundleThrowsForUnknownFile() { - let testBundle = NSBundle(forClass: self.dynamicType) - let template = try? Template(named: "test2.html", inBundle: testBundle) - XCTAssertNil(template) - } - - func testTemplateWithNSURL() { - let testBundle = NSBundle(forClass: self.dynamicType) - let URL = testBundle.URLForResource("test", withExtension: "html") - XCTAssertNotNil(URL) - let template = try? Template(URL: URL!) - let context = Context(dictionary: [ "target": "Kyle" ]) - - XCTAssertNotNil(template) - let result = try? template!.render(context) - XCTAssertEqual(result, "Hello Kyle!") - } -} diff --git a/StencilTests/VariableTests.swift b/StencilTests/VariableTests.swift deleted file mode 100644 index 363556f..0000000 --- a/StencilTests/VariableTests.swift +++ /dev/null @@ -1,62 +0,0 @@ -import Foundation -import XCTest -import Stencil - -@objc class Object : NSObject { - let title = "Hello World" -} - -class VariableTests: XCTestCase { - var context:Context! - - override func setUp() { - context = Context(dictionary: [ - "name": "Kyle", - "contacts": [ "Katie", "Orta", ], - "profiles": [ "github": "kylef", ], - "object": Object(), - ]) - } - - func testResolvingStringLiteral() { - let variable = Variable("\"name\"") - let result = variable.resolve(context) as! String - XCTAssertEqual(result, "name") - } - - func testResolvingVariable() { - let variable = Variable("name") - let result = variable.resolve(context) as! String - XCTAssertEqual(result, "Kyle") - } - - func testResolvingItemFromDictionary() { - let variable = Variable("profiles.github") - let result = variable.resolve(context) as! String - XCTAssertEqual(result, "kylef") - } - - func testResolvingItemFromArrayWithIndex() { - let variable = Variable("contacts.0") - let result = variable.resolve(context) as! String - XCTAssertEqual(result, "Katie") - } - - func testResolvingFirstItemFromArray() { - let variable = Variable("contacts.first") - let result = variable.resolve(context) as! String - XCTAssertEqual(result, "Katie") - } - - func testResolvingLastItemFromArray() { - let variable = Variable("contacts.last") - let result = variable.resolve(context) as! String - XCTAssertEqual(result, "Orta") - } - - func testResolvingValueViaKVO() { - let variable = Variable("object.title") - let result = variable.resolve(context) as! String - XCTAssertEqual(result, "Hello World") - } -} diff --git a/circle.yml b/circle.yml index 7988c8e..df52107 100644 --- a/circle.yml +++ b/circle.yml @@ -1,11 +1,17 @@ machine: xcode: version: "7.0" + environment: + XCODE_SCHEME: NONE + XCODE_PROJECT: NONE + +dependencies: + post: + - brew install --HEAD kylef/formulae/conche test: override: - - set -o pipefail && xcodebuild -workspace Stencil.xcworkspace -scheme Stencil test | tee $CIRCLE_ARTIFACTS/xcode_raw_ios.log | xcpretty -c - - pod lib lint + - conche test deployment: release: