From 8fb4c0ceb67888af694c443fecd30467983bdd7d Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Sun, 20 Aug 2017 18:20:16 +0200 Subject: [PATCH 01/10] Split Filters+Strings files; --- Pods/Pods.xcodeproj/project.pbxproj | 38 +-- Sources/Filters+Strings+Boolean.swift | 54 ++++ Sources/Filters+Strings+Lettercase.swift | 158 +++++++++++ Sources/Filters+Strings+Mutations.swift | 154 +++++++++++ Sources/Filters+Strings.swift | 338 ----------------------- 5 files changed, 388 insertions(+), 354 deletions(-) create mode 100644 Sources/Filters+Strings+Boolean.swift create mode 100644 Sources/Filters+Strings+Lettercase.swift create mode 100644 Sources/Filters+Strings+Mutations.swift delete mode 100644 Sources/Filters+Strings.swift diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj index c5b89400..54376513 100644 --- a/Pods/Pods.xcodeproj/project.pbxproj +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 47; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ @@ -15,7 +15,7 @@ 163B9DC44E3DEC34D9DE044C115A2E4C /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 206DA29D6C35E14C93D2BF773A66C54C /* Environment.swift */; }; 16F84ECA579F82D43E35D6A53B3EB93B /* IfTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = D887BD539929925B9535E5136F861F20 /* IfTag.swift */; }; 1CE827F4243BD57BF4EE0632156D47C2 /* Template.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69F59D1438D9D791C86016D62F2078B9 /* Template.swift */; }; - 261ED3A17531A5012E5E2EA78BC189C3 /* Filters+Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47DB41142F62E8B5174F3DF281DCD5E3 /* Filters+Strings.swift */; }; + 261ED3A17531A5012E5E2EA78BC189C3 /* Filters+Strings+Boolean.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47DB41142F62E8B5174F3DF281DCD5E3 /* Filters+Strings+Boolean.swift */; }; 2636E7A890C8E29D410238FE1578E827 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 11F7F2E3F010D24453E40821938EF8EC /* Foundation.framework */; }; 2C8F0FFFA142A9B47B5FC10AC0774C42 /* ForTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CCB7B571DD30214319D05B2A2D01268 /* ForTag.swift */; }; 3170167B02A05241EBADAC85C3B55E34 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = D12438B80ED47AD60857542BE0113ED7 /* Expression.swift */; }; @@ -29,6 +29,8 @@ 5DEF23C8870F6D838AF561730C58977B /* Lexer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A007C042C580A003C9B6DB5AD1B534 /* Lexer.swift */; }; 6272EE69D3F5DE1DF030E2B979A19909 /* PathKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B85A6D36EC20031BC5814F8D8D514E8 /* PathKit.swift */; }; 637082FCBAF4D5BA395484A67D546E17 /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E92B989035E25169DF9300616F23AAB /* Environment.swift */; }; + 6D1EF02C1F49E85D00EA91EF /* Filters+Strings+Mutations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D1EF02B1F49E85D00EA91EF /* Filters+Strings+Mutations.swift */; }; + 6D1EF0301F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D1EF02F1F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift */; }; 722E658DD92366A84D5A67AF0DB0E9C9 /* Context.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8923816ECEE63BE56AD67F2A147EF787 /* Context.swift */; }; 759D827E105015554B9EEB00299E122C /* MapNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD4D19D5AAB65F338845041B6F767D2 /* MapNode.swift */; }; 77D8C016692C6E24EBEDF607455B0B0E /* PathKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0436538F42B0A2EC1C972F8EE47937E0 /* PathKit.framework */; }; @@ -124,30 +126,32 @@ 2E6EDE0590FA1A030C93F83C2EEFC65C /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Tests.release.xcconfig"; sourceTree = ""; }; 2E92B989035E25169DF9300616F23AAB /* Environment.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Environment.swift; path = Sources/Environment.swift; sourceTree = ""; }; 31A007C042C580A003C9B6DB5AD1B534 /* Lexer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Lexer.swift; path = Sources/Lexer.swift; sourceTree = ""; }; - 351D229C0FCFC7B3571671631111EE1C /* Pods_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_Tests.framework; path = "Pods-Tests.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + 351D229C0FCFC7B3571671631111EE1C /* Pods_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B1C96CDE10E0238E81B06BD4DF23DAE /* Stencil-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Stencil-umbrella.h"; sourceTree = ""; }; 3D9976A9FB02F6316003996E10007AEE /* FilterTag.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FilterTag.swift; path = Sources/FilterTag.swift; sourceTree = ""; }; 4309AA7478DD6B254C478AE5335748BA /* Pods-Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Tests-acknowledgements.plist"; sourceTree = ""; }; 461150690A6BC561CA3FA50B494C0503 /* StencilSwiftTemplate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StencilSwiftTemplate.swift; path = Sources/StencilSwiftTemplate.swift; sourceTree = ""; }; - 47DB41142F62E8B5174F3DF281DCD5E3 /* Filters+Strings.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Filters+Strings.swift"; path = "Sources/Filters+Strings.swift"; sourceTree = ""; }; - 49BCF2F8CB8DBEA0E51D00A9DE6AC7F5 /* Stencil.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Stencil.framework; path = Stencil.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 4F35C03EE539651D8168B79F18A1DF5B /* Pods-Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-Tests.modulemap"; sourceTree = ""; }; + 47DB41142F62E8B5174F3DF281DCD5E3 /* Filters+Strings+Boolean.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Filters+Strings+Boolean.swift"; path = "Sources/Filters+Strings+Boolean.swift"; sourceTree = ""; }; + 49BCF2F8CB8DBEA0E51D00A9DE6AC7F5 /* Stencil.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Stencil.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4F35C03EE539651D8168B79F18A1DF5B /* Pods-Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-Tests.modulemap"; sourceTree = ""; }; 52E08CA96B2F20724148FF5361AD7206 /* Pods-Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Tests-umbrella.h"; sourceTree = ""; }; 5B85A6D36EC20031BC5814F8D8D514E8 /* PathKit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PathKit.swift; path = Sources/PathKit.swift; sourceTree = ""; }; 5C8E1A8F9B02B1B71DEA7E55021BAC8A /* StencilSwiftKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "StencilSwiftKit-prefix.pch"; sourceTree = ""; }; 5DA2EACBDBA3A368338F5A0A5C89D62D /* SetNode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SetNode.swift; path = Sources/SetNode.swift; sourceTree = ""; }; 5EC97AE8648FE62BB73FAED74FEDA009 /* StencilSwiftKit.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = StencilSwiftKit.xcconfig; sourceTree = ""; }; 69F59D1438D9D791C86016D62F2078B9 /* Template.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Template.swift; path = Sources/Template.swift; sourceTree = ""; }; + 6D1EF02B1F49E85D00EA91EF /* Filters+Strings+Mutations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Filters+Strings+Mutations.swift"; path = "Sources/Filters+Strings+Mutations.swift"; sourceTree = ""; }; + 6D1EF02F1F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Filters+Strings+Lettercase.swift"; path = "Sources/Filters+Strings+Lettercase.swift"; sourceTree = ""; }; 6E3DE9DADD254D64C598089530A5932B /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 749318FE61E9EC318ED19250766267E2 /* Stencil-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Stencil-prefix.pch"; sourceTree = ""; }; - 7DB310C86ADAE310E9DF111FDD487FAF /* StencilSwiftKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = StencilSwiftKit.framework; path = StencilSwiftKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7DB310C86ADAE310E9DF111FDD487FAF /* StencilSwiftKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StencilSwiftKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 8923816ECEE63BE56AD67F2A147EF787 /* Context.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Context.swift; path = Sources/Context.swift; sourceTree = ""; }; 8CA49A25561E541E61395E8C64512F22 /* PathKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PathKit-dummy.m"; sourceTree = ""; }; 8CCB7B571DD30214319D05B2A2D01268 /* ForTag.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ForTag.swift; path = Sources/ForTag.swift; sourceTree = ""; }; 8FFA7DA1538F3CB30DA2B5074B573E52 /* Tokenizer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Tokenizer.swift; path = Sources/Tokenizer.swift; sourceTree = ""; }; - 919EAEDB009B1AA70C305AC91847AC41 /* PathKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = PathKit.modulemap; sourceTree = ""; }; + 919EAEDB009B1AA70C305AC91847AC41 /* PathKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = PathKit.modulemap; sourceTree = ""; }; 93A3BA06E90B797B9126411EF449E61E /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 9A68FA9661EC6B4BA5415DDD474F7F00 /* Stencil.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Stencil.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A5E20637D178539A5F5705320E6AAD3F /* Include.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Include.swift; path = Sources/Include.swift; sourceTree = ""; }; B0A2858DB038304C5239C4738D8E3643 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -159,15 +163,15 @@ C1E8657D8A2E60CA5179FDE94F283B2A /* PathKit.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PathKit.xcconfig; sourceTree = ""; }; C3CE7EC198DBFD800632E7DF1604AD47 /* SwiftIdentifier.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftIdentifier.swift; path = Sources/SwiftIdentifier.swift; sourceTree = ""; }; C62389B5756FDBA46714335EE5B2079D /* PathKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PathKit-umbrella.h"; sourceTree = ""; }; - C68D522B00371B910EC16028EBD47384 /* PathKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = PathKit.framework; path = PathKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C68D522B00371B910EC16028EBD47384 /* PathKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PathKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C74DCC10F6CC9FB70BEF27A2183A5B4F /* Filters.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Filters.swift; path = Sources/Filters.swift; sourceTree = ""; }; D12438B80ED47AD60857542BE0113ED7 /* Expression.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Expression.swift; path = Sources/Expression.swift; sourceTree = ""; }; D5846CC8D36C9B97B51ACC82399D6A12 /* PathKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PathKit-prefix.pch"; sourceTree = ""; }; D680408E4561AB716D64F6AB22F9FB68 /* CallMacroNodes.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CallMacroNodes.swift; path = Sources/CallMacroNodes.swift; sourceTree = ""; }; - D6C2D28B3980163C3F38852C8437E5C2 /* Stencil.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = Stencil.modulemap; sourceTree = ""; }; + D6C2D28B3980163C3F38852C8437E5C2 /* Stencil.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = Stencil.modulemap; sourceTree = ""; }; D887BD539929925B9535E5136F861F20 /* IfTag.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IfTag.swift; path = Sources/IfTag.swift; sourceTree = ""; }; DFD4D19D5AAB65F338845041B6F767D2 /* MapNode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MapNode.swift; path = Sources/MapNode.swift; sourceTree = ""; }; - E9C51D01C292146479413F2582CA6927 /* StencilSwiftKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = StencilSwiftKit.modulemap; sourceTree = ""; }; + E9C51D01C292146479413F2582CA6927 /* StencilSwiftKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = StencilSwiftKit.modulemap; sourceTree = ""; }; F53DDD89903CC6468CD0F552B6F9620C /* StencilSwiftKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "StencilSwiftKit-umbrella.h"; sourceTree = ""; }; F95B3E1482647F7822F3C47A7AE76BD9 /* Parameters.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Parameters.swift; path = Sources/Parameters.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -354,7 +358,6 @@ 17E001094F65D072A6D5E4A0C7F419BD /* Variable.swift */, 472C634E13CB5E53C65AA1985F35C13D /* Support Files */, ); - name = Stencil; path = Stencil; sourceTree = ""; }; @@ -364,7 +367,6 @@ 5B85A6D36EC20031BC5814F8D8D514E8 /* PathKit.swift */, 693A6FD601295700FF3115312779D86A /* Support Files */, ); - name = PathKit; path = PathKit; sourceTree = ""; }; @@ -385,7 +387,9 @@ 2E92B989035E25169DF9300616F23AAB /* Environment.swift */, 0C6D246B203676EC17FA9473D97CB418 /* Filters.swift */, 02B0A9A1128124B1A17D5AB1E23A0A45 /* Filters+Numbers.swift */, - 47DB41142F62E8B5174F3DF281DCD5E3 /* Filters+Strings.swift */, + 6D1EF02F1F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift */, + 6D1EF02B1F49E85D00EA91EF /* Filters+Strings+Mutations.swift */, + 47DB41142F62E8B5174F3DF281DCD5E3 /* Filters+Strings+Boolean.swift */, DFD4D19D5AAB65F338845041B6F767D2 /* MapNode.swift */, F95B3E1482647F7822F3C47A7AE76BD9 /* Parameters.swift */, 5DA2EACBDBA3A368338F5A0A5C89D62D /* SetNode.swift */, @@ -591,14 +595,16 @@ 7DEDE215489DFFE058F997C06CD9111D /* Context.swift in Sources */, 637082FCBAF4D5BA395484A67D546E17 /* Environment.swift in Sources */, C95B8343B8C61222772740E5865B7005 /* Filters+Numbers.swift in Sources */, - 261ED3A17531A5012E5E2EA78BC189C3 /* Filters+Strings.swift in Sources */, + 261ED3A17531A5012E5E2EA78BC189C3 /* Filters+Strings+Boolean.swift in Sources */, 8BC329E46538413C89622D36F9599D40 /* Filters.swift in Sources */, + 6D1EF0301F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift in Sources */, 759D827E105015554B9EEB00299E122C /* MapNode.swift in Sources */, 33D90C9CAF6D9EEC537D8AF319C624C6 /* Parameters.swift in Sources */, C372EA8DC7AE1A9B3DB7EB2278C29338 /* SetNode.swift in Sources */, 85B93ADD2E39D138FCFFBB16141221D7 /* StencilSwiftKit-dummy.m in Sources */, E50716969C524070F2EA8DF037ED4CC2 /* StencilSwiftTemplate.swift in Sources */, 4D564D819736B2A614641ABC770C82C1 /* SwiftIdentifier.swift in Sources */, + 6D1EF02C1F49E85D00EA91EF /* Filters+Strings+Mutations.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sources/Filters+Strings+Boolean.swift b/Sources/Filters+Strings+Boolean.swift new file mode 100644 index 00000000..069cba7a --- /dev/null +++ b/Sources/Filters+Strings+Boolean.swift @@ -0,0 +1,54 @@ +// +// StencilSwiftKit +// Copyright (c) 2017 SwiftGen +// MIT Licence +// + +import Foundation +import Stencil + +extension Filters { + enum Strings { + /// Checks if the given string contains given substring + /// + /// - Parameters: + /// - value: the string value to check if it contains substring + /// - arguments: the arguments to the function; expecting one string argument - substring + /// - Returns: the result whether true or not + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or + /// if number of arguments is not one or if the given argument isn't a string + static func contains(_ value: Any?, arguments: [Any?]) throws -> Bool { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + guard let substring = arguments.first as? String else { throw Filters.Error.invalidInputType } + return string.contains(substring) + } + + /// Checks if the given string has given prefix + /// + /// - Parameters: + /// - value: the string value to check if it has prefix + /// - arguments: the arguments to the function; expecting one string argument - prefix + /// - Returns: the result whether true or not + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or + /// if number of arguments is not one or if the given argument isn't a string + static func hasPrefix(_ value: Any?, arguments: [Any?]) throws -> Bool { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + guard let prefix = arguments.first as? String else { throw Filters.Error.invalidInputType } + return string.hasPrefix(prefix) + } + + /// Checks if the given string has given suffix + /// + /// - Parameters: + /// - value: the string value to check if it has prefix + /// - arguments: the arguments to the function; expecting one string argument - suffix + /// - Returns: the result whether true or not + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or + /// if number of arguments is not one or if the given argument isn't a string + static func hasSuffix(_ value: Any?, arguments: [Any?]) throws -> Bool { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + guard let suffix = arguments.first as? String else { throw Filters.Error.invalidInputType } + return string.hasSuffix(suffix) + } + } +} diff --git a/Sources/Filters+Strings+Lettercase.swift b/Sources/Filters+Strings+Lettercase.swift new file mode 100644 index 00000000..594137b1 --- /dev/null +++ b/Sources/Filters+Strings+Lettercase.swift @@ -0,0 +1,158 @@ +// +// Filters+Strings+Lettercase.swift +// Pods +// +// Created by Anton Domashnev on 20.08.17. +// +// + +import Foundation +import Stencil + +extension Filters.Strings { + /// Lowers the first letter of the string + /// e.g. "People picker" gives "people picker", "Sports Stats" gives "sports Stats" + static func lowerFirstLetter(_ value: Any?) throws -> Any? { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + let first = String(string.characters.prefix(1)).lowercased() + let other = String(string.characters.dropFirst(1)) + return first + other + } + + /// If the string starts with only one uppercase letter, lowercase that first letter + /// If the string starts with multiple uppercase letters, lowercase those first letters + /// up to the one before the last uppercase one, but only if the last one is followed by + /// a lowercase character. + /// e.g. "PeoplePicker" gives "peoplePicker" but "URLChooser" gives "urlChooser" + static func lowerFirstWord(_ value: Any?) throws -> Any? { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + let cs = CharacterSet.uppercaseLetters + let scalars = string.unicodeScalars + let start = scalars.startIndex + var idx = start + while let scalar = UnicodeScalar(scalars[idx].value), cs.contains(scalar) && idx <= scalars.endIndex { + idx = scalars.index(after: idx) + } + if idx > scalars.index(after: start) && idx < scalars.endIndex, + let scalar = UnicodeScalar(scalars[idx].value), + CharacterSet.lowercaseLetters.contains(scalar) { + idx = scalars.index(before: idx) + } + let transformed = String(scalars[start.. Any? { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + return titlecase(string) + } + + /// Converts snake_case to camelCase. Takes an optional Bool argument for removing any resulting + /// leading '_' characters, which defaults to false + /// + /// - Parameters: + /// - value: the value to be processed + /// - arguments: the arguments to the function; expecting zero or one boolean argument + /// - Returns: the camel case string + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string + static func snakeToCamelCase(_ value: Any?, arguments: [Any?]) throws -> Any? { + let stripLeading = try Filters.parseBool(from: arguments, required: false) ?? false + guard let string = value as? String else { throw Filters.Error.invalidInputType } + + return try snakeToCamelCase(string, stripLeading: stripLeading) + } + + /// Converts camelCase to snake_case. Takes an optional Bool argument for making the string lower case, + /// which defaults to true + /// + /// - Parameters: + /// - value: the value to be processed + /// - arguments: the arguments to the function; expecting zero or one boolean argument + /// - Returns: the snake case string + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string + static func camelToSnakeCase(_ value: Any?, arguments: [Any?]) throws -> Any? { + let toLower = try Filters.parseBool(from: arguments, required: false) ?? true + guard let string = value as? String else { throw Filters.Error.invalidInputType } + + let snakeCase = try snakecase(string) + if toLower { + return snakeCase.lowercased() + } + return snakeCase + } + + /// Converts snake_case to camelCase, stripping prefix underscores if needed + /// + /// - Parameters: + /// - string: the value to be processed + /// - stripLeading: if false, will preserve leading underscores + /// - Returns: the camel case string + static func snakeToCamelCase(_ string: String, stripLeading: Bool) throws -> String { + let unprefixed: String + if try containsAnyLowercasedChar(string) { + let comps = string.components(separatedBy: "_") + unprefixed = comps.map { titlecase($0) }.joined(separator: "") + } else { + let comps = try snakecase(string).components(separatedBy: "_") + unprefixed = comps.map { $0.capitalized }.joined(separator: "") + } + + // only if passed true, strip the prefix underscores + var prefixUnderscores = "" + if !stripLeading { + for scalar in string.unicodeScalars { + guard scalar == "_" else { break } + prefixUnderscores += "_" + } + } + + return prefixUnderscores + unprefixed + } + + // MARK: - Private + + private static func containsAnyLowercasedChar(_ string: String) throws -> Bool { + let lowercaseCharRegex = try NSRegularExpression(pattern: "[a-z]", options: .dotMatchesLineSeparators) + let fullRange = NSRange(location: 0, length: string.unicodeScalars.count) + return lowercaseCharRegex.firstMatch(in: string, options: .reportCompletion, range: fullRange) != nil + } + + /// This returns the string with its first parameter uppercased. + /// - note: This is quite similar to `capitalise` except that this filter doesn't + /// lowercase the rest of the string but keeps it untouched. + /// + /// - Parameter string: The string to titleCase + /// - Returns: The string with its first character uppercased, and the rest of the string unchanged. + private static func titlecase(_ string: String) -> String { + guard let first = string.unicodeScalars.first else { return string } + return String(first).uppercased() + String(string.unicodeScalars.dropFirst()) + } + + /// This returns the snake cased variant of the string. + /// + /// - Parameter string: The string to snake_case + /// - Returns: The string snake cased from either snake_cased or camelCased string. + private static func snakecase(_ string: String) throws -> String { + let longUpper = try NSRegularExpression(pattern: "([A-Z\\d]+)([A-Z][a-z])", options: .dotMatchesLineSeparators) + let camelCased = try NSRegularExpression(pattern: "([a-z\\d])([A-Z])", options: .dotMatchesLineSeparators) + + let fullRange = NSRange(location: 0, length: string.unicodeScalars.count) + var result = longUpper.stringByReplacingMatches(in: string, + options: .reportCompletion, + range: fullRange, + withTemplate: "$1_$2") + result = camelCased.stringByReplacingMatches(in: result, + options: .reportCompletion, + range: fullRange, + withTemplate: "$1_$2") + return result.replacingOccurrences(of: "-", with: "_") + } +} diff --git a/Sources/Filters+Strings+Mutations.swift b/Sources/Filters+Strings+Mutations.swift new file mode 100644 index 00000000..216d8147 --- /dev/null +++ b/Sources/Filters+Strings+Mutations.swift @@ -0,0 +1,154 @@ +// +// Filters+Strings+Mutations.swift +// Pods +// +// Created by Anton Domashnev on 20.08.17. +// +// + +import Foundation +import Stencil + +enum RemoveNewlinesModes: String { + case all, leading +} + +enum SwiftIdentifierModes: String { + case normal, pretty +} + +extension Filters.Strings { + fileprivate static let reservedKeywords = [ + "associatedtype", "class", "deinit", "enum", "extension", + "fileprivate", "func", "import", "init", "inout", "internal", + "let", "open", "operator", "private", "protocol", "public", + "static", "struct", "subscript", "typealias", "var", "break", + "case", "continue", "default", "defer", "do", "else", + "fallthrough", "for", "guard", "if", "in", "repeat", "return", + "switch", "where", "while", "as", "Any", "catch", "false", "is", + "nil", "rethrows", "super", "self", "Self", "throw", "throws", + "true", "try", "_", "#available", "#colorLiteral", "#column", + "#else", "#elseif", "#endif", "#file", "#fileLiteral", + "#function", "#if", "#imageLiteral", "#line", "#selector", + "#sourceLocation", "associativity", "convenience", "dynamic", + "didSet", "final", "get", "infix", "indirect", "lazy", "left", + "mutating", "none", "nonmutating", "optional", "override", + "postfix", "precedence", "prefix", "Protocol", "required", + "right", "set", "Type", "unowned", "weak", "willSet" + ] + + static func escapeReservedKeywords(value: Any?) throws -> Any? { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + return escapeReservedKeywords(in: string) + } + + /// Replaces in the given string the given substring with the replacement + /// "people picker", replacing "picker" with "life" gives "people life" + /// + /// - Parameters: + /// - value: the value to be processed + /// - arguments: the arguments to the function; expecting two arguments: substring, replacement + /// - Returns: the results string + /// - Throws: FilterError.invalidInputType if the value parameter or argunemts aren't string + static func replace(_ value: Any?, arguments: [Any?]) throws -> Any? { + guard let source = value as? String, + arguments.count == 2, + let substring = arguments[0] as? String, + let replacement = arguments[1] as? String else { + throw Filters.Error.invalidInputType + } + return source.replacingOccurrences(of: substring, with: replacement) + } + + /// Converts an arbitrary string to a valid swift identifier. Takes an optional Mode argument: + /// - normal (default): uppercase the first character, prefix with an underscore if starting + /// with a number, replace invalid characters by underscores + /// - leading: same as the above, but apply the snaceToCamelCase filter first for a nicer + /// identifier + /// + /// - Parameters: + /// - value: the value to be processed + /// - arguments: the arguments to the function; expecting zero or one mode argument + /// - Returns: the identifier string + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string + static func swiftIdentifier(_ value: Any?, arguments: [Any?]) throws -> Any? { + guard var string = value as? String else { throw Filters.Error.invalidInputType } + let mode = try Filters.parseEnum(from: arguments, default: SwiftIdentifierModes.normal) + + switch mode { + case .normal: + return SwiftIdentifier.identifier(from: string, replaceWithUnderscores: true) + case .pretty: + string = SwiftIdentifier.identifier(from: string, replaceWithUnderscores: true) + string = try snakeToCamelCase(string, stripLeading: true) + return SwiftIdentifier.prefixWithUnderscoreIfNeeded(string: string) + } + } + + /// Converts a file path to just the filename, stripping any path components before it. + /// + /// - Parameter value: the value to be processed + /// - Returns: the basename of the path + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string + static func basename(_ value: Any?) throws -> Any? { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + return (string as NSString).lastPathComponent + } + + /// Converts a file path to just the path without the filename. + /// + /// - Parameter value: the value to be processed + /// - Returns: the dirname of the path + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string + static func dirname(_ value: Any?) throws -> Any? { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + return (string as NSString).deletingLastPathComponent + } + + /// Removes newlines and other whitespace from a string. Takes an optional Mode argument: + /// - all (default): remove all newlines and whitespaces + /// - leading: remove newlines and only leading whitespaces + /// + /// - Parameters: + /// - value: the value to be processed + /// - arguments: the arguments to the function; expecting zero or one mode argument + /// - Returns: the trimmed string + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string + static func removeNewlines(_ value: Any?, arguments: [Any?]) throws -> Any? { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + let mode = try Filters.parseEnum(from: arguments, default: RemoveNewlinesModes.all) + + switch mode { + case .all: + return string + .components(separatedBy: .whitespacesAndNewlines) + .joined() + case .leading: + return string + .components(separatedBy: .newlines) + .map(removeLeadingWhitespaces(from:)) + .joined() + .trimmingCharacters(in: .whitespaces) + } + } + + // MARK: - Private methods + + private static func removeLeadingWhitespaces(from string: String) -> String { + let chars = string.unicodeScalars.drop { CharacterSet.whitespaces.contains($0) } + return String(chars) + } + + // MARK: - Private + + /// Checks if the string is one of the reserved keywords and if so, escapes it using backticks + /// + /// - Parameter in: the string to possibly escape + /// - Returns: if the string is a reserved keyword, the escaped string, otherwise the original one + private static func escapeReservedKeywords(in string: String) -> String { + guard reservedKeywords.contains(string) else { + return string + } + return "`\(string)`" + } +} diff --git a/Sources/Filters+Strings.swift b/Sources/Filters+Strings.swift deleted file mode 100644 index b4671b46..00000000 --- a/Sources/Filters+Strings.swift +++ /dev/null @@ -1,338 +0,0 @@ -// -// StencilSwiftKit -// Copyright (c) 2017 SwiftGen -// MIT Licence -// - -import Foundation -import Stencil - -enum RemoveNewlinesModes: String { - case all, leading -} - -enum SwiftIdentifierModes: String { - case normal, pretty -} - -extension Filters { - enum Strings { - fileprivate static let reservedKeywords = [ - "associatedtype", "class", "deinit", "enum", "extension", - "fileprivate", "func", "import", "init", "inout", "internal", - "let", "open", "operator", "private", "protocol", "public", - "static", "struct", "subscript", "typealias", "var", "break", - "case", "continue", "default", "defer", "do", "else", - "fallthrough", "for", "guard", "if", "in", "repeat", "return", - "switch", "where", "while", "as", "Any", "catch", "false", "is", - "nil", "rethrows", "super", "self", "Self", "throw", "throws", - "true", "try", "_", "#available", "#colorLiteral", "#column", - "#else", "#elseif", "#endif", "#file", "#fileLiteral", - "#function", "#if", "#imageLiteral", "#line", "#selector", - "#sourceLocation", "associativity", "convenience", "dynamic", - "didSet", "final", "get", "infix", "indirect", "lazy", "left", - "mutating", "none", "nonmutating", "optional", "override", - "postfix", "precedence", "prefix", "Protocol", "required", - "right", "set", "Type", "unowned", "weak", "willSet" - ] - - /// Replaces in the given string the given substring with the replacement - /// "people picker", replacing "picker" with "life" gives "people life" - /// - /// - Parameters: - /// - value: the value to be processed - /// - arguments: the arguments to the function; expecting two arguments: substring, replacement - /// - Returns: the results string - /// - Throws: FilterError.invalidInputType if the value parameter or argunemts aren't string - static func replace(_ value: Any?, arguments: [Any?]) throws -> Any? { - guard let source = value as? String, - arguments.count == 2, - let substring = arguments[0] as? String, - let replacement = arguments[1] as? String else { - throw Filters.Error.invalidInputType - } - return source.replacingOccurrences(of: substring, with: replacement) - } - - /// Converts an arbitrary string to a valid swift identifier. Takes an optional Mode argument: - /// - normal (default): uppercase the first character, prefix with an underscore if starting - /// with a number, replace invalid characters by underscores - /// - leading: same as the above, but apply the snaceToCamelCase filter first for a nicer - /// identifier - /// - /// - Parameters: - /// - value: the value to be processed - /// - arguments: the arguments to the function; expecting zero or one mode argument - /// - Returns: the identifier string - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string - static func swiftIdentifier(_ value: Any?, arguments: [Any?]) throws -> Any? { - guard var string = value as? String else { throw Filters.Error.invalidInputType } - let mode = try Filters.parseEnum(from: arguments, default: SwiftIdentifierModes.normal) - - switch mode { - case .normal: - return SwiftIdentifier.identifier(from: string, replaceWithUnderscores: true) - case .pretty: - string = SwiftIdentifier.identifier(from: string, replaceWithUnderscores: true) - string = try snakeToCamelCase(string, stripLeading: true) - return SwiftIdentifier.prefixWithUnderscoreIfNeeded(string: string) - } - } - - /// Lowers the first letter of the string - /// e.g. "People picker" gives "people picker", "Sports Stats" gives "sports Stats" - static func lowerFirstLetter(_ value: Any?) throws -> Any? { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - let first = String(string.characters.prefix(1)).lowercased() - let other = String(string.characters.dropFirst(1)) - return first + other - } - - /// If the string starts with only one uppercase letter, lowercase that first letter - /// If the string starts with multiple uppercase letters, lowercase those first letters - /// up to the one before the last uppercase one, but only if the last one is followed by - /// a lowercase character. - /// e.g. "PeoplePicker" gives "peoplePicker" but "URLChooser" gives "urlChooser" - static func lowerFirstWord(_ value: Any?) throws -> Any? { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - let cs = CharacterSet.uppercaseLetters - let scalars = string.unicodeScalars - let start = scalars.startIndex - var idx = start - while let scalar = UnicodeScalar(scalars[idx].value), cs.contains(scalar) && idx <= scalars.endIndex { - idx = scalars.index(after: idx) - } - if idx > scalars.index(after: start) && idx < scalars.endIndex, - let scalar = UnicodeScalar(scalars[idx].value), - CharacterSet.lowercaseLetters.contains(scalar) { - idx = scalars.index(before: idx) - } - let transformed = String(scalars[start.. Any? { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - return titlecase(string) - } - - /// Converts snake_case to camelCase. Takes an optional Bool argument for removing any resulting - /// leading '_' characters, which defaults to false - /// - /// - Parameters: - /// - value: the value to be processed - /// - arguments: the arguments to the function; expecting zero or one boolean argument - /// - Returns: the camel case string - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string - static func snakeToCamelCase(_ value: Any?, arguments: [Any?]) throws -> Any? { - let stripLeading = try Filters.parseBool(from: arguments, required: false) ?? false - guard let string = value as? String else { throw Filters.Error.invalidInputType } - - return try snakeToCamelCase(string, stripLeading: stripLeading) - } - - /// Converts camelCase to snake_case. Takes an optional Bool argument for making the string lower case, - /// which defaults to true - /// - /// - Parameters: - /// - value: the value to be processed - /// - arguments: the arguments to the function; expecting zero or one boolean argument - /// - Returns: the snake case string - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string - static func camelToSnakeCase(_ value: Any?, arguments: [Any?]) throws -> Any? { - let toLower = try Filters.parseBool(from: arguments, required: false) ?? true - guard let string = value as? String else { throw Filters.Error.invalidInputType } - - let snakeCase = try snakecase(string) - if toLower { - return snakeCase.lowercased() - } - return snakeCase - } - - static func escapeReservedKeywords(value: Any?) throws -> Any? { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - return escapeReservedKeywords(in: string) - } - - /// Removes newlines and other whitespace from a string. Takes an optional Mode argument: - /// - all (default): remove all newlines and whitespaces - /// - leading: remove newlines and only leading whitespaces - /// - /// - Parameters: - /// - value: the value to be processed - /// - arguments: the arguments to the function; expecting zero or one mode argument - /// - Returns: the trimmed string - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string - static func removeNewlines(_ value: Any?, arguments: [Any?]) throws -> Any? { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - let mode = try Filters.parseEnum(from: arguments, default: RemoveNewlinesModes.all) - - switch mode { - case .all: - return string - .components(separatedBy: .whitespacesAndNewlines) - .joined() - case .leading: - return string - .components(separatedBy: .newlines) - .map(removeLeadingWhitespaces(from:)) - .joined() - .trimmingCharacters(in: .whitespaces) - } - } - - /// Checks if the given string contains given substring - /// - /// - Parameters: - /// - value: the string value to check if it contains substring - /// - arguments: the arguments to the function; expecting one string argument - substring - /// - Returns: the result whether true or not - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or - /// if number of arguments is not one or if the given argument isn't a string - static func contains(_ value: Any?, arguments: [Any?]) throws -> Bool { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - guard let substring = arguments.first as? String else { throw Filters.Error.invalidInputType } - return string.contains(substring) - } - - /// Checks if the given string has given prefix - /// - /// - Parameters: - /// - value: the string value to check if it has prefix - /// - arguments: the arguments to the function; expecting one string argument - prefix - /// - Returns: the result whether true or not - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or - /// if number of arguments is not one or if the given argument isn't a string - static func hasPrefix(_ value: Any?, arguments: [Any?]) throws -> Bool { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - guard let prefix = arguments.first as? String else { throw Filters.Error.invalidInputType } - return string.hasPrefix(prefix) - } - - /// Checks if the given string has given suffix - /// - /// - Parameters: - /// - value: the string value to check if it has prefix - /// - arguments: the arguments to the function; expecting one string argument - suffix - /// - Returns: the result whether true or not - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or - /// if number of arguments is not one or if the given argument isn't a string - static func hasSuffix(_ value: Any?, arguments: [Any?]) throws -> Bool { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - guard let suffix = arguments.first as? String else { throw Filters.Error.invalidInputType } - return string.hasSuffix(suffix) - } - - /// Converts a file path to just the filename, stripping any path components before it. - /// - /// - Parameter value: the value to be processed - /// - Returns: the basename of the path - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string - static func basename(_ value: Any?) throws -> Any? { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - return (string as NSString).lastPathComponent - } - - /// Converts a file path to just the path without the filename. - /// - /// - Parameter value: the value to be processed - /// - Returns: the dirname of the path - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string - static func dirname(_ value: Any?) throws -> Any? { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - return (string as NSString).deletingLastPathComponent - } - - // MARK: - Private methods - - private static func removeLeadingWhitespaces(from string: String) -> String { - let chars = string.unicodeScalars.drop { CharacterSet.whitespaces.contains($0) } - return String(chars) - } - - /// Converts snake_case to camelCase, stripping prefix underscores if needed - /// - /// - Parameters: - /// - string: the value to be processed - /// - stripLeading: if false, will preserve leading underscores - /// - Returns: the camel case string - static func snakeToCamelCase(_ string: String, stripLeading: Bool) throws -> String { - let unprefixed: String - if try containsAnyLowercasedChar(string) { - let comps = string.components(separatedBy: "_") - unprefixed = comps.map { titlecase($0) }.joined(separator: "") - } else { - let comps = try snakecase(string).components(separatedBy: "_") - unprefixed = comps.map { $0.capitalized }.joined(separator: "") - } - - // only if passed true, strip the prefix underscores - var prefixUnderscores = "" - if !stripLeading { - for scalar in string.unicodeScalars { - guard scalar == "_" else { break } - prefixUnderscores += "_" - } - } - - return prefixUnderscores + unprefixed - } - - /// This returns the string with its first parameter uppercased. - /// - note: This is quite similar to `capitalise` except that this filter doesn't - /// lowercase the rest of the string but keeps it untouched. - /// - /// - Parameter string: The string to titleCase - /// - Returns: The string with its first character uppercased, and the rest of the string unchanged. - private static func titlecase(_ string: String) -> String { - guard let first = string.unicodeScalars.first else { return string } - return String(first).uppercased() + String(string.unicodeScalars.dropFirst()) - } - - private static func containsAnyLowercasedChar(_ string: String) throws -> Bool { - let lowercaseCharRegex = try NSRegularExpression(pattern: "[a-z]", options: .dotMatchesLineSeparators) - let fullRange = NSRange(location: 0, length: string.unicodeScalars.count) - return lowercaseCharRegex.firstMatch(in: string, options: .reportCompletion, range: fullRange) != nil - } - - /// This returns the snake cased variant of the string. - /// - /// - Parameter string: The string to snake_case - /// - Returns: The string snake cased from either snake_cased or camelCased string. - private static func snakecase(_ string: String) throws -> String { - let longUpper = try NSRegularExpression(pattern: "([A-Z\\d]+)([A-Z][a-z])", options: .dotMatchesLineSeparators) - let camelCased = try NSRegularExpression(pattern: "([a-z\\d])([A-Z])", options: .dotMatchesLineSeparators) - - let fullRange = NSRange(location: 0, length: string.unicodeScalars.count) - var result = longUpper.stringByReplacingMatches(in: string, - options: .reportCompletion, - range: fullRange, - withTemplate: "$1_$2") - result = camelCased.stringByReplacingMatches(in: result, - options: .reportCompletion, - range: fullRange, - withTemplate: "$1_$2") - return result.replacingOccurrences(of: "-", with: "_") - } - - /// Checks if the string is one of the reserved keywords and if so, escapes it using backticks - /// - /// - Parameter in: the string to possibly escape - /// - Returns: if the string is a reserved keyword, the escaped string, otherwise the original one - private static func escapeReservedKeywords(in string: String) -> String { - guard reservedKeywords.contains(string) else { - return string - } - return "`\(string)`" - } - } -} From a696b5544269a3a7e09b6be2fa04b3e1b3ec7967 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Sun, 20 Aug 2017 18:32:22 +0200 Subject: [PATCH 02/10] Small cleanup; --- Sources/Filters+Strings+Lettercase.swift | 23 +++++++++++------------ Sources/Filters+Strings+Mutations.swift | 12 ++++-------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/Sources/Filters+Strings+Lettercase.swift b/Sources/Filters+Strings+Lettercase.swift index 594137b1..30c4dc6c 100644 --- a/Sources/Filters+Strings+Lettercase.swift +++ b/Sources/Filters+Strings+Lettercase.swift @@ -1,9 +1,7 @@ // -// Filters+Strings+Lettercase.swift -// Pods -// -// Created by Anton Domashnev on 20.08.17. -// +// StencilSwiftKit +// Copyright (c) 2017 SwiftGen +// MIT Licence // import Foundation @@ -107,14 +105,15 @@ extension Filters.Strings { // only if passed true, strip the prefix underscores var prefixUnderscores = "" - if !stripLeading { - for scalar in string.unicodeScalars { - guard scalar == "_" else { break } - prefixUnderscores += "_" - } + var result: String { return prefixUnderscores + unprefixed } + if stripLeading { + return result } - - return prefixUnderscores + unprefixed + for scalar in string.unicodeScalars { + guard scalar == "_" else { break } + prefixUnderscores += "_" + } + return result } // MARK: - Private diff --git a/Sources/Filters+Strings+Mutations.swift b/Sources/Filters+Strings+Mutations.swift index 216d8147..38a8a388 100644 --- a/Sources/Filters+Strings+Mutations.swift +++ b/Sources/Filters+Strings+Mutations.swift @@ -1,9 +1,7 @@ // -// Filters+Strings+Mutations.swift -// Pods -// -// Created by Anton Domashnev on 20.08.17. -// +// StencilSwiftKit +// Copyright (c) 2017 SwiftGen +// MIT Licence // import Foundation @@ -132,15 +130,13 @@ extension Filters.Strings { } } - // MARK: - Private methods + // MARK: - Private private static func removeLeadingWhitespaces(from string: String) -> String { let chars = string.unicodeScalars.drop { CharacterSet.whitespaces.contains($0) } return String(chars) } - // MARK: - Private - /// Checks if the string is one of the reserved keywords and if so, escapes it using backticks /// /// - Parameter in: the string to possibly escape From 2304150902a70a5b247c90b5721590644a237c15 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Sun, 20 Aug 2017 18:34:30 +0200 Subject: [PATCH 03/10] Update changelog; --- CHANGELOG.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c02176a..447306ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,23 +18,25 @@ _None_ ### Internal Changes -_None_ +* Refactoring of `Filters+Strings`. + [Antondomashnev](https://github.com/antondomashnev) + [#59](https://github.com/SwiftGen/StencilSwiftKit/pull/63) ## 2.1.0 ### New Features * Added the `basename` and `dirname` string filters for getting a filename, or parent folder (respectively), out of a path. - [David Jennes](https://github.com/djbe) + [David Jennes](https://github.com/djbe) [#60](https://github.com/SwiftGen/StencilSwiftKit/pull/60) * Modify the `swiftIdentifier` string filter to accept an optional "pretty" mode, to also apply the `snakeToCamelCase` filter and other manipulations if needed for a "prettier" but still valid identifier. - [David Jennes](https://github.com/djbe) + [David Jennes](https://github.com/djbe) [#61](https://github.com/SwiftGen/StencilSwiftKit/pull/61) ### Internal Changes * Ensure `swiftlint` is run using `bundler`. - [David Jennes](https://github.com/djbe) + [David Jennes](https://github.com/djbe) [#59](https://github.com/SwiftGen/StencilSwiftKit/pull/59) ## 2.0.1 From 73ca5da3b47ddbacb6b1eab81c04182fbdb26870 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Sun, 20 Aug 2017 22:31:53 +0200 Subject: [PATCH 04/10] Create a base Filters+Strings; --- Pods/Pods.xcodeproj/project.pbxproj | 8 ++++++-- Sources/Filters+Strings+Boolean.swift | 28 +++++++++++++-------------- Sources/Filters+Strings.swift | 13 +++++++++++++ 3 files changed, 32 insertions(+), 17 deletions(-) create mode 100644 Sources/Filters+Strings.swift diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj index 54376513..adeafd43 100644 --- a/Pods/Pods.xcodeproj/project.pbxproj +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -31,6 +31,7 @@ 637082FCBAF4D5BA395484A67D546E17 /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E92B989035E25169DF9300616F23AAB /* Environment.swift */; }; 6D1EF02C1F49E85D00EA91EF /* Filters+Strings+Mutations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D1EF02B1F49E85D00EA91EF /* Filters+Strings+Mutations.swift */; }; 6D1EF0301F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D1EF02F1F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift */; }; + 6D1EF0341F4A25CA00EA91EF /* Filters+Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D1EF0331F4A25CA00EA91EF /* Filters+Strings.swift */; }; 722E658DD92366A84D5A67AF0DB0E9C9 /* Context.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8923816ECEE63BE56AD67F2A147EF787 /* Context.swift */; }; 759D827E105015554B9EEB00299E122C /* MapNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD4D19D5AAB65F338845041B6F767D2 /* MapNode.swift */; }; 77D8C016692C6E24EBEDF607455B0B0E /* PathKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0436538F42B0A2EC1C972F8EE47937E0 /* PathKit.framework */; }; @@ -142,6 +143,7 @@ 69F59D1438D9D791C86016D62F2078B9 /* Template.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Template.swift; path = Sources/Template.swift; sourceTree = ""; }; 6D1EF02B1F49E85D00EA91EF /* Filters+Strings+Mutations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Filters+Strings+Mutations.swift"; path = "Sources/Filters+Strings+Mutations.swift"; sourceTree = ""; }; 6D1EF02F1F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Filters+Strings+Lettercase.swift"; path = "Sources/Filters+Strings+Lettercase.swift"; sourceTree = ""; }; + 6D1EF0331F4A25CA00EA91EF /* Filters+Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Filters+Strings.swift"; path = "Sources/Filters+Strings.swift"; sourceTree = ""; }; 6E3DE9DADD254D64C598089530A5932B /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 749318FE61E9EC318ED19250766267E2 /* Stencil-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Stencil-prefix.pch"; sourceTree = ""; }; 7DB310C86ADAE310E9DF111FDD487FAF /* StencilSwiftKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StencilSwiftKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -390,6 +392,7 @@ 6D1EF02F1F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift */, 6D1EF02B1F49E85D00EA91EF /* Filters+Strings+Mutations.swift */, 47DB41142F62E8B5174F3DF281DCD5E3 /* Filters+Strings+Boolean.swift */, + 6D1EF0331F4A25CA00EA91EF /* Filters+Strings.swift */, DFD4D19D5AAB65F338845041B6F767D2 /* MapNode.swift */, F95B3E1482647F7822F3C47A7AE76BD9 /* Parameters.swift */, 5DA2EACBDBA3A368338F5A0A5C89D62D /* SetNode.swift */, @@ -595,16 +598,17 @@ 7DEDE215489DFFE058F997C06CD9111D /* Context.swift in Sources */, 637082FCBAF4D5BA395484A67D546E17 /* Environment.swift in Sources */, C95B8343B8C61222772740E5865B7005 /* Filters+Numbers.swift in Sources */, + 6D1EF0341F4A25CA00EA91EF /* Filters+Strings.swift in Sources */, + 6D1EF02C1F49E85D00EA91EF /* Filters+Strings+Mutations.swift in Sources */, 261ED3A17531A5012E5E2EA78BC189C3 /* Filters+Strings+Boolean.swift in Sources */, - 8BC329E46538413C89622D36F9599D40 /* Filters.swift in Sources */, 6D1EF0301F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift in Sources */, + 8BC329E46538413C89622D36F9599D40 /* Filters.swift in Sources */, 759D827E105015554B9EEB00299E122C /* MapNode.swift in Sources */, 33D90C9CAF6D9EEC537D8AF319C624C6 /* Parameters.swift in Sources */, C372EA8DC7AE1A9B3DB7EB2278C29338 /* SetNode.swift in Sources */, 85B93ADD2E39D138FCFFBB16141221D7 /* StencilSwiftKit-dummy.m in Sources */, E50716969C524070F2EA8DF037ED4CC2 /* StencilSwiftTemplate.swift in Sources */, 4D564D819736B2A614641ABC770C82C1 /* SwiftIdentifier.swift in Sources */, - 6D1EF02C1F49E85D00EA91EF /* Filters+Strings+Mutations.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sources/Filters+Strings+Boolean.swift b/Sources/Filters+Strings+Boolean.swift index 069cba7a..35d0f399 100644 --- a/Sources/Filters+Strings+Boolean.swift +++ b/Sources/Filters+Strings+Boolean.swift @@ -7,22 +7,21 @@ import Foundation import Stencil -extension Filters { - enum Strings { +extension Filters.Strings { /// Checks if the given string contains given substring /// /// - Parameters: /// - value: the string value to check if it contains substring /// - arguments: the arguments to the function; expecting one string argument - substring /// - Returns: the result whether true or not - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or /// if number of arguments is not one or if the given argument isn't a string static func contains(_ value: Any?, arguments: [Any?]) throws -> Bool { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - guard let substring = arguments.first as? String else { throw Filters.Error.invalidInputType } - return string.contains(substring) + guard let string = value as? String else { throw Filters.Error.invalidInputType } + guard let substring = arguments.first as? String else { throw Filters.Error.invalidInputType } + return string.contains(substring) } - + /// Checks if the given string has given prefix /// /// - Parameters: @@ -32,11 +31,11 @@ extension Filters { /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or /// if number of arguments is not one or if the given argument isn't a string static func hasPrefix(_ value: Any?, arguments: [Any?]) throws -> Bool { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - guard let prefix = arguments.first as? String else { throw Filters.Error.invalidInputType } - return string.hasPrefix(prefix) + guard let string = value as? String else { throw Filters.Error.invalidInputType } + guard let prefix = arguments.first as? String else { throw Filters.Error.invalidInputType } + return string.hasPrefix(prefix) } - + /// Checks if the given string has given suffix /// /// - Parameters: @@ -46,9 +45,8 @@ extension Filters { /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or /// if number of arguments is not one or if the given argument isn't a string static func hasSuffix(_ value: Any?, arguments: [Any?]) throws -> Bool { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - guard let suffix = arguments.first as? String else { throw Filters.Error.invalidInputType } - return string.hasSuffix(suffix) + guard let string = value as? String else { throw Filters.Error.invalidInputType } + guard let suffix = arguments.first as? String else { throw Filters.Error.invalidInputType } + return string.hasSuffix(suffix) } - } } diff --git a/Sources/Filters+Strings.swift b/Sources/Filters+Strings.swift new file mode 100644 index 00000000..27346c15 --- /dev/null +++ b/Sources/Filters+Strings.swift @@ -0,0 +1,13 @@ +// +// StencilSwiftKit +// Copyright (c) 2017 SwiftGen +// MIT Licence +// + +import Foundation +import Stencil + +extension Filters { + enum Strings { + } +} From c4686c3e07f683ce1ea162a598a1161deeb808ce Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Sun, 20 Aug 2017 22:43:01 +0200 Subject: [PATCH 05/10] Remove titlecase function; --- Sources/Filters+Strings+Lettercase.swift | 26 +++++++++++++----------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/Sources/Filters+Strings+Lettercase.swift b/Sources/Filters+Strings+Lettercase.swift index 30c4dc6c..73817d5f 100644 --- a/Sources/Filters+Strings+Lettercase.swift +++ b/Sources/Filters+Strings+Lettercase.swift @@ -40,8 +40,8 @@ extension Filters.Strings { return transformed } - /// Lowers the first letter of the string - /// e.g. "People picker" gives "people picker", "Sports Stats" gives "sports Stats" + /// Uppers the first letter of the string + /// e.g. "people picker" gives "People picker", "sports Stats" gives "Sports Stats" /// /// - Parameters: /// - value: the value to uppercase first letter of @@ -50,7 +50,7 @@ extension Filters.Strings { /// - Throws: FilterError.invalidInputType if the value parameter isn't a string static func upperFirstLetter(_ value: Any?) throws -> Any? { guard let string = value as? String else { throw Filters.Error.invalidInputType } - return titlecase(string) + return upperFirstLetter(string) } /// Converts snake_case to camelCase. Takes an optional Bool argument for removing any resulting @@ -97,7 +97,7 @@ extension Filters.Strings { let unprefixed: String if try containsAnyLowercasedChar(string) { let comps = string.components(separatedBy: "_") - unprefixed = comps.map { titlecase($0) }.joined(separator: "") + unprefixed = comps.map { upperFirstLetter($0) }.joined(separator: "") } else { let comps = try snakecase(string).components(separatedBy: "_") unprefixed = comps.map { $0.capitalized }.joined(separator: "") @@ -124,15 +124,17 @@ extension Filters.Strings { return lowercaseCharRegex.firstMatch(in: string, options: .reportCompletion, range: fullRange) != nil } - /// This returns the string with its first parameter uppercased. - /// - note: This is quite similar to `capitalise` except that this filter doesn't - /// lowercase the rest of the string but keeps it untouched. + /// Uppers the first letter of the string + /// e.g. "people picker" gives "People picker", "sports Stats" gives "Sports Stats" /// - /// - Parameter string: The string to titleCase - /// - Returns: The string with its first character uppercased, and the rest of the string unchanged. - private static func titlecase(_ string: String) -> String { - guard let first = string.unicodeScalars.first else { return string } - return String(first).uppercased() + String(string.unicodeScalars.dropFirst()) + /// - Parameters: + /// - value: the value to uppercase first letter of + /// - arguments: the arguments to the function; expecting zero + /// - Returns: the string with first letter being uppercased + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string + private static func upperFirstLetter(_ value: String) -> String { + guard let first = value.unicodeScalars.first else { return value } + return String(first).uppercased() + String(value.unicodeScalars.dropFirst()) } /// This returns the snake cased variant of the string. From 3f2af0d6fb66424bbb6b66f716287370e9401791 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Sun, 20 Aug 2017 22:52:53 +0200 Subject: [PATCH 06/10] Fix Extension.registerStencilSwiftExtensions codebeat issue; --- Pods/Pods.xcodeproj/project.pbxproj | 2 +- Sources/Environment.swift | 30 ++++++++++++++++++++--------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj index adeafd43..c7b63d9e 100644 --- a/Pods/Pods.xcodeproj/project.pbxproj +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -125,7 +125,7 @@ 2802FBB7965EA4284282522D369C6ECC /* Loader.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Loader.swift; path = Sources/Loader.swift; sourceTree = ""; }; 2C8AAD97E22D7F6B08B73B0AE02BFA6D /* Pods-Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Tests-resources.sh"; sourceTree = ""; }; 2E6EDE0590FA1A030C93F83C2EEFC65C /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Tests.release.xcconfig"; sourceTree = ""; }; - 2E92B989035E25169DF9300616F23AAB /* Environment.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Environment.swift; path = Sources/Environment.swift; sourceTree = ""; }; + 2E92B989035E25169DF9300616F23AAB /* Environment.swift */ = {isa = PBXFileReference; includeInIndex = 1; indentWidth = 2; lastKnownFileType = sourcecode.swift; name = Environment.swift; path = Sources/Environment.swift; sourceTree = ""; tabWidth = 2; }; 31A007C042C580A003C9B6DB5AD1B534 /* Lexer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Lexer.swift; path = Sources/Lexer.swift; sourceTree = ""; }; 351D229C0FCFC7B3571671631111EE1C /* Pods_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 3B1C96CDE10E0238E81B06BD4DF23DAE /* Stencil-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Stencil-umbrella.h"; sourceTree = ""; }; diff --git a/Sources/Environment.swift b/Sources/Environment.swift index 2df9258b..1aa620f3 100644 --- a/Sources/Environment.swift +++ b/Sources/Environment.swift @@ -8,11 +8,20 @@ import Stencil public extension Extension { public func registerStencilSwiftExtensions() { - registerTag("set", parser: SetNode.parse) - registerTag("macro", parser: MacroNode.parse) - registerTag("call", parser: CallNode.parse) - registerTag("map", parser: MapNode.parse) - + registerTags() + registerStringsFilters() + registerNumbersFilters() + } + + // MARK: - Private + + private func registerNumbersFilters() { + registerFilter("hexToInt", filter: Filters.Numbers.hexToInt) + registerFilter("int255toFloat", filter: Filters.Numbers.int255toFloat) + registerFilter("percent", filter: Filters.Numbers.percent) + } + + private func registerStringsFilters() { registerFilter("basename", filter: Filters.Strings.basename) registerFilter("camelToSnakeCase", filter: Filters.Strings.camelToSnakeCase) registerFilter("contains", filter: Filters.Strings.contains) @@ -28,10 +37,13 @@ public extension Extension { registerFilter("swiftIdentifier", filter: Filters.Strings.swiftIdentifier) registerFilter("titlecase", filter: Filters.Strings.upperFirstLetter) registerFilter("upperFirstLetter", filter: Filters.Strings.upperFirstLetter) - - registerFilter("hexToInt", filter: Filters.Numbers.hexToInt) - registerFilter("int255toFloat", filter: Filters.Numbers.int255toFloat) - registerFilter("percent", filter: Filters.Numbers.percent) + } + + private func registerTags() { + registerTag("set", parser: SetNode.parse) + registerTag("macro", parser: MacroNode.parse) + registerTag("call", parser: CallNode.parse) + registerTag("map", parser: MapNode.parse) } } From 58fd00d1a315b146aa307073970ec1e87698814c Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Sun, 20 Aug 2017 23:04:31 +0200 Subject: [PATCH 07/10] Fix Parameters.parse codebeat issue; --- Pods/Pods.xcodeproj/project.pbxproj | 2 +- Sources/Parameters.swift | 50 ++++++++++++++++++----------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj index c7b63d9e..47d83047 100644 --- a/Pods/Pods.xcodeproj/project.pbxproj +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -175,7 +175,7 @@ DFD4D19D5AAB65F338845041B6F767D2 /* MapNode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MapNode.swift; path = Sources/MapNode.swift; sourceTree = ""; }; E9C51D01C292146479413F2582CA6927 /* StencilSwiftKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = StencilSwiftKit.modulemap; sourceTree = ""; }; F53DDD89903CC6468CD0F552B6F9620C /* StencilSwiftKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "StencilSwiftKit-umbrella.h"; sourceTree = ""; }; - F95B3E1482647F7822F3C47A7AE76BD9 /* Parameters.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Parameters.swift; path = Sources/Parameters.swift; sourceTree = ""; }; + F95B3E1482647F7822F3C47A7AE76BD9 /* Parameters.swift */ = {isa = PBXFileReference; includeInIndex = 1; indentWidth = 2; lastKnownFileType = sourcecode.swift; name = Parameters.swift; path = Sources/Parameters.swift; sourceTree = ""; tabWidth = 2; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ diff --git a/Sources/Parameters.swift b/Sources/Parameters.swift index 51dad58e..d4b9a27a 100644 --- a/Sources/Parameters.swift +++ b/Sources/Parameters.swift @@ -60,36 +60,50 @@ public enum Parameters { private static func parse(parameter: Parameter, result: StringDict) throws -> StringDict { let parts = parameter.key.components(separatedBy: ".") let key = parts.first ?? "" - var result = result // validate key guard validate(key: key) else { throw Error.invalidKey(key: parameter.key, value: parameter.value) } // no sub keys, may need to convert to array if repeat key if possible if parts.count == 1 { - if let current = result[key] as? [Any] { - result[key] = current + [parameter.value] - } else if let current = result[key] as? String { - result[key] = [current, parameter.value] - } else if let current = result[key] { - throw Error.invalidStructure(key: key, oldValue: current, newValue: parameter.value) - } else { - result[key] = parameter.value - } - } else if parts.count > 1 { - guard result[key] is StringDict || result[key] == nil else { - throw Error.invalidStructure(key: key, oldValue: result[key] ?? "", newValue: parameter.value) - } + return try parse(key: key, parameter: parameter, result: result) + } - // recurse into sub keys - let current = result[key] as? StringDict ?? StringDict() - let sub = (key: parts.suffix(from: 1).joined(separator: "."), value: parameter.value) - result[key] = try parse(parameter: sub, result: current) + guard result[key] is StringDict || result[key] == nil else { + throw Error.invalidStructure(key: key, oldValue: result[key] ?? "", newValue: parameter.value) } + // recurse into sub keys + var result = result + let current = result[key] as? StringDict ?? StringDict() + let sub = (key: parts.suffix(from: 1).joined(separator: "."), value: parameter.value) + result[key] = try parse(parameter: sub, result: current) return result } + /// Parse a single `key=value` (or `key`) string and inserts it into + /// an existing StringDict dictionary being built. + /// + /// - Parameters: + /// - parameter: The parameter/string (key/value pair) to parse, where key doesn't have sub keys + /// - result: The dictionary currently being built and to which to add the value + /// - Returns: The new content of the dictionary being built after inserting the new parsed value + /// - Throws: `Parameters.Error` + private static func parse(key: String, parameter: Parameter, result: StringDict) throws -> StringDict { + var result = result + if let current = result[key] as? [Any] { + result[key] = current + [parameter.value] + } else if let current = result[key] as? String { + result[key] = [current, parameter.value] + } else if let current = result[key] { + throw Error.invalidStructure(key: key, oldValue: current, newValue: parameter.value) + } else { + result[key] = parameter.value + } + return result + } + + // a valid key is not empty and only alphanumerical or dot private static func validate(key: String) -> Bool { return !key.isEmpty && From 9b979f4af8f9d8ff9a650f5927883ff9835bc856 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Sun, 20 Aug 2017 23:08:05 +0200 Subject: [PATCH 08/10] Fix public Parameters.parse codebeat issue; --- Sources/Parameters.swift | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Sources/Parameters.swift b/Sources/Parameters.swift index d4b9a27a..c47524ca 100644 --- a/Sources/Parameters.swift +++ b/Sources/Parameters.swift @@ -31,17 +31,7 @@ public enum Parameters { /// - Returns: A structured dictionary matching the list of keys /// - Throws: `Parameters.Error` public static func parse(items: [String]) throws -> StringDict { - let parameters: [Parameter] = try items.map { item in - let parts = item.components(separatedBy: "=") - if parts.count >= 2 { - return (key: parts[0], value: parts.dropFirst().joined(separator: "=")) - } else if let part = parts.first, parts.count == 1 && validate(key: part) { - return (key: part, value: true) - } else { - throw Error.invalidSyntax(value: item) - } - } - + let parameters: [Parameter] = try items.map(createParameter) return try parameters.reduce(StringDict()) { try parse(parameter: $1, result: $0) } @@ -103,7 +93,6 @@ public enum Parameters { return result } - // a valid key is not empty and only alphanumerical or dot private static func validate(key: String) -> Bool { return !key.isEmpty && @@ -115,4 +104,15 @@ public enum Parameters { result.insert(".") return result.inverted }() + + private static func createParameter(from string: String) throws -> Parameter { + let parts = string.components(separatedBy: "=") + if parts.count >= 2 { + return (key: parts[0], value: parts.dropFirst().joined(separator: "=")) + } else if let part = parts.first, parts.count == 1 && validate(key: part) { + return (key: part, value: true) + } else { + throw Error.invalidSyntax(value: string) + } + } } From 362f5bc95f60395146f948a9c0b140a58c67ffbc Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Sun, 20 Aug 2017 23:24:17 +0200 Subject: [PATCH 09/10] Fix swiftlint warnings; --- Pods/Pods.xcodeproj/project.pbxproj | 2 +- Sources/Environment.swift | 8 +-- Sources/Filters+Strings+Boolean.swift | 82 +++++++++++++-------------- Sources/Parameters.swift | 2 +- 4 files changed, 47 insertions(+), 47 deletions(-) diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj index 47d83047..c033dfd2 100644 --- a/Pods/Pods.xcodeproj/project.pbxproj +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -132,7 +132,7 @@ 3D9976A9FB02F6316003996E10007AEE /* FilterTag.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FilterTag.swift; path = Sources/FilterTag.swift; sourceTree = ""; }; 4309AA7478DD6B254C478AE5335748BA /* Pods-Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Tests-acknowledgements.plist"; sourceTree = ""; }; 461150690A6BC561CA3FA50B494C0503 /* StencilSwiftTemplate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StencilSwiftTemplate.swift; path = Sources/StencilSwiftTemplate.swift; sourceTree = ""; }; - 47DB41142F62E8B5174F3DF281DCD5E3 /* Filters+Strings+Boolean.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Filters+Strings+Boolean.swift"; path = "Sources/Filters+Strings+Boolean.swift"; sourceTree = ""; }; + 47DB41142F62E8B5174F3DF281DCD5E3 /* Filters+Strings+Boolean.swift */ = {isa = PBXFileReference; includeInIndex = 1; indentWidth = 2; lastKnownFileType = sourcecode.swift; name = "Filters+Strings+Boolean.swift"; path = "Sources/Filters+Strings+Boolean.swift"; sourceTree = ""; tabWidth = 2; }; 49BCF2F8CB8DBEA0E51D00A9DE6AC7F5 /* Stencil.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Stencil.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4F35C03EE539651D8168B79F18A1DF5B /* Pods-Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-Tests.modulemap"; sourceTree = ""; }; 52E08CA96B2F20724148FF5361AD7206 /* Pods-Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Tests-umbrella.h"; sourceTree = ""; }; diff --git a/Sources/Environment.swift b/Sources/Environment.swift index 1aa620f3..0fab7edc 100644 --- a/Sources/Environment.swift +++ b/Sources/Environment.swift @@ -12,15 +12,15 @@ public extension Extension { registerStringsFilters() registerNumbersFilters() } - + // MARK: - Private - + private func registerNumbersFilters() { registerFilter("hexToInt", filter: Filters.Numbers.hexToInt) registerFilter("int255toFloat", filter: Filters.Numbers.int255toFloat) registerFilter("percent", filter: Filters.Numbers.percent) } - + private func registerStringsFilters() { registerFilter("basename", filter: Filters.Strings.basename) registerFilter("camelToSnakeCase", filter: Filters.Strings.camelToSnakeCase) @@ -38,7 +38,7 @@ public extension Extension { registerFilter("titlecase", filter: Filters.Strings.upperFirstLetter) registerFilter("upperFirstLetter", filter: Filters.Strings.upperFirstLetter) } - + private func registerTags() { registerTag("set", parser: SetNode.parse) registerTag("macro", parser: MacroNode.parse) diff --git a/Sources/Filters+Strings+Boolean.swift b/Sources/Filters+Strings+Boolean.swift index 35d0f399..03ff6a25 100644 --- a/Sources/Filters+Strings+Boolean.swift +++ b/Sources/Filters+Strings+Boolean.swift @@ -8,45 +8,45 @@ import Foundation import Stencil extension Filters.Strings { - /// Checks if the given string contains given substring - /// - /// - Parameters: - /// - value: the string value to check if it contains substring - /// - arguments: the arguments to the function; expecting one string argument - substring - /// - Returns: the result whether true or not - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or - /// if number of arguments is not one or if the given argument isn't a string - static func contains(_ value: Any?, arguments: [Any?]) throws -> Bool { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - guard let substring = arguments.first as? String else { throw Filters.Error.invalidInputType } - return string.contains(substring) - } - - /// Checks if the given string has given prefix - /// - /// - Parameters: - /// - value: the string value to check if it has prefix - /// - arguments: the arguments to the function; expecting one string argument - prefix - /// - Returns: the result whether true or not - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or - /// if number of arguments is not one or if the given argument isn't a string - static func hasPrefix(_ value: Any?, arguments: [Any?]) throws -> Bool { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - guard let prefix = arguments.first as? String else { throw Filters.Error.invalidInputType } - return string.hasPrefix(prefix) - } - - /// Checks if the given string has given suffix - /// - /// - Parameters: - /// - value: the string value to check if it has prefix - /// - arguments: the arguments to the function; expecting one string argument - suffix - /// - Returns: the result whether true or not - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or - /// if number of arguments is not one or if the given argument isn't a string - static func hasSuffix(_ value: Any?, arguments: [Any?]) throws -> Bool { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - guard let suffix = arguments.first as? String else { throw Filters.Error.invalidInputType } - return string.hasSuffix(suffix) - } + /// Checks if the given string contains given substring + /// + /// - Parameters: + /// - value: the string value to check if it contains substring + /// - arguments: the arguments to the function; expecting one string argument - substring + /// - Returns: the result whether true or not + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or + /// if number of arguments is not one or if the given argument isn't a string + static func contains(_ value: Any?, arguments: [Any?]) throws -> Bool { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + guard let substring = arguments.first as? String else { throw Filters.Error.invalidInputType } + return string.contains(substring) + } + + /// Checks if the given string has given prefix + /// + /// - Parameters: + /// - value: the string value to check if it has prefix + /// - arguments: the arguments to the function; expecting one string argument - prefix + /// - Returns: the result whether true or not + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or + /// if number of arguments is not one or if the given argument isn't a string + static func hasPrefix(_ value: Any?, arguments: [Any?]) throws -> Bool { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + guard let prefix = arguments.first as? String else { throw Filters.Error.invalidInputType } + return string.hasPrefix(prefix) + } + + /// Checks if the given string has given suffix + /// + /// - Parameters: + /// - value: the string value to check if it has prefix + /// - arguments: the arguments to the function; expecting one string argument - suffix + /// - Returns: the result whether true or not + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string or + /// if number of arguments is not one or if the given argument isn't a string + static func hasSuffix(_ value: Any?, arguments: [Any?]) throws -> Bool { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + guard let suffix = arguments.first as? String else { throw Filters.Error.invalidInputType } + return string.hasSuffix(suffix) + } } diff --git a/Sources/Parameters.swift b/Sources/Parameters.swift index c47524ca..90e4fe30 100644 --- a/Sources/Parameters.swift +++ b/Sources/Parameters.swift @@ -104,7 +104,7 @@ public enum Parameters { result.insert(".") return result.inverted }() - + private static func createParameter(from string: String) throws -> Parameter { let parts = string.components(separatedBy: "=") if parts.count >= 2 { From c4852fd808ad1e1ac2dfc3f6afbc9ce9fc772481 Mon Sep 17 00:00:00 2001 From: Anton Domashnev Date: Tue, 22 Aug 2017 16:28:19 +0200 Subject: [PATCH 10/10] Workaround the spm build issues; --- Package.pins | 24 ++ Package.resolved | 34 +++ Podfile.lock | 2 +- Pods/Local Podspecs/Stencil.podspec.json | 32 --- .../StencilSwiftKit.podspec.json | 17 +- Pods/Manifest.lock | 2 +- Pods/Pods.xcodeproj/project.pbxproj | 198 ++++++------- ...rings.swift => Filters+Strings+Base.swift} | 0 Sources/Filters+Strings+Lettercase.swift | 262 +++++++++--------- 9 files changed, 306 insertions(+), 265 deletions(-) create mode 100644 Package.pins create mode 100644 Package.resolved delete mode 100644 Pods/Local Podspecs/Stencil.podspec.json rename Sources/{Filters+Strings.swift => Filters+Strings+Base.swift} (100%) diff --git a/Package.pins b/Package.pins new file mode 100644 index 00000000..cb8e82b8 --- /dev/null +++ b/Package.pins @@ -0,0 +1,24 @@ +{ + "autoPin": true, + "pins": [ + { + "package": "PathKit", + "reason": null, + "repositoryURL": "https://github.com/kylef/PathKit.git", + "version": "0.8.0" + }, + { + "package": "Spectre", + "reason": null, + "repositoryURL": "https://github.com/kylef/Spectre.git", + "version": "0.7.2" + }, + { + "package": "Stencil", + "reason": null, + "repositoryURL": "https://github.com/kylef/Stencil.git", + "version": "0.9.0" + } + ], + "version": 1 +} \ No newline at end of file diff --git a/Package.resolved b/Package.resolved new file mode 100644 index 00000000..09b5c956 --- /dev/null +++ b/Package.resolved @@ -0,0 +1,34 @@ +{ + "object": { + "pins": [ + { + "package": "PathKit", + "repositoryURL": "https://github.com/kylef/PathKit.git", + "state": { + "branch": null, + "revision": "891a3fec2699fc43aed18b7649950677c0152a22", + "version": "0.8.0" + } + }, + { + "package": "Spectre", + "repositoryURL": "https://github.com/kylef/Spectre.git", + "state": { + "branch": null, + "revision": "e46b75cf03ad5e563b4b0a5068d3d6f04d77d80b", + "version": "0.7.2" + } + }, + { + "package": "Stencil", + "repositoryURL": "https://github.com/kylef/Stencil.git", + "state": { + "branch": null, + "revision": "65a461d0a103896c8ff7e3f17f7be1a5badadeb0", + "version": "0.9.0" + } + } + ] + }, + "version": 1 +} diff --git a/Podfile.lock b/Podfile.lock index 82e1e472..5511d73e 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -15,7 +15,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: PathKit: dcab05d701474011aae0e40cf892298a831f63d6 Stencil: 510f0b0518a366b67b6a9c5085a0399741b6d2f9 - StencilSwiftKit: 76100a047f59c3358a3abe0cd5cc99db19a3dcc7 + StencilSwiftKit: 682c70ed061e6a91774da284a4370799692e518a PODFILE CHECKSUM: 81c0228e2e71a9683d0eed53bd9f6bd1165815b7 diff --git a/Pods/Local Podspecs/Stencil.podspec.json b/Pods/Local Podspecs/Stencil.podspec.json deleted file mode 100644 index fa52f697..00000000 --- a/Pods/Local Podspecs/Stencil.podspec.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "name": "Stencil", - "version": "0.7.1", - "summary": "Stencil is a simple and powerful template language for Swift.", - "homepage": "https://stencil.fuller.li", - "license": { - "type": "BSD", - "file": "LICENSE" - }, - "authors": { - "Kyle Fuller": "kyle@fuller.li" - }, - "social_media_url": "https://twitter.com/kylefuller", - "source": { - "git": "https://github.com/kylef/Stencil.git", - "tag": "0.7.1" - }, - "source_files": [ - "Sources/*.swift" - ], - "platforms": { - "ios": "8.0", - "osx": "10.9", - "tvos": "9.0" - }, - "requires_arc": true, - "dependencies": { - "PathKit": [ - "~> 0.7.0" - ] - } -} diff --git a/Pods/Local Podspecs/StencilSwiftKit.podspec.json b/Pods/Local Podspecs/StencilSwiftKit.podspec.json index 7d87c628..f2a42b11 100644 --- a/Pods/Local Podspecs/StencilSwiftKit.podspec.json +++ b/Pods/Local Podspecs/StencilSwiftKit.podspec.json @@ -16,7 +16,22 @@ "git": "https://github.com/SwiftGen/StencilSwiftKit.git", "tag": "2.1.0" }, - "source_files": "Sources/**/*.swift", + "source_files": [ + "Sources/CallMacroNodes.swift", + "Sources/Environment.swift", + "Sources/Context.swift", + "Sources/Filters.swift", + "Sources/Filters+Numbers.swift", + "Sources/Filters+Strings.swift", + "Sources/Filters+Strings+Boolean.swift", + "Sources/Filters+Strings+Lettercase.swift", + "Sources/Filters+Strings+Mutations.swift", + "Sources/MapNode.swift", + "Sources/Parameters.swift", + "Sources/SetNode.swift", + "Sources/StencilSwiftTemplate.swift", + "Sources/SwoftIdentifier.swift" + ], "dependencies": { "Stencil": [ "~> 0.9.0" diff --git a/Pods/Manifest.lock b/Pods/Manifest.lock index 82e1e472..5511d73e 100644 --- a/Pods/Manifest.lock +++ b/Pods/Manifest.lock @@ -15,7 +15,7 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: PathKit: dcab05d701474011aae0e40cf892298a831f63d6 Stencil: 510f0b0518a366b67b6a9c5085a0399741b6d2f9 - StencilSwiftKit: 76100a047f59c3358a3abe0cd5cc99db19a3dcc7 + StencilSwiftKit: 682c70ed061e6a91774da284a4370799692e518a PODFILE CHECKSUM: 81c0228e2e71a9683d0eed53bd9f6bd1165815b7 diff --git a/Pods/Pods.xcodeproj/project.pbxproj b/Pods/Pods.xcodeproj/project.pbxproj index c033dfd2..f49ec750 100644 --- a/Pods/Pods.xcodeproj/project.pbxproj +++ b/Pods/Pods.xcodeproj/project.pbxproj @@ -15,46 +15,46 @@ 163B9DC44E3DEC34D9DE044C115A2E4C /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 206DA29D6C35E14C93D2BF773A66C54C /* Environment.swift */; }; 16F84ECA579F82D43E35D6A53B3EB93B /* IfTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = D887BD539929925B9535E5136F861F20 /* IfTag.swift */; }; 1CE827F4243BD57BF4EE0632156D47C2 /* Template.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69F59D1438D9D791C86016D62F2078B9 /* Template.swift */; }; - 261ED3A17531A5012E5E2EA78BC189C3 /* Filters+Strings+Boolean.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47DB41142F62E8B5174F3DF281DCD5E3 /* Filters+Strings+Boolean.swift */; }; + 25133010A93E9FE79DD02F53F12C26D2 /* MapNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = C58F57104A480134D785C5B0D14A7DE7 /* MapNode.swift */; }; 2636E7A890C8E29D410238FE1578E827 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 11F7F2E3F010D24453E40821938EF8EC /* Foundation.framework */; }; 2C8F0FFFA142A9B47B5FC10AC0774C42 /* ForTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CCB7B571DD30214319D05B2A2D01268 /* ForTag.swift */; }; + 2CBF2B3563EE7F6006A506310244966A /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89406CF74F5F8BA2BEE26EBB7E7F1FFA /* Environment.swift */; }; 3170167B02A05241EBADAC85C3B55E34 /* Expression.swift in Sources */ = {isa = PBXBuildFile; fileRef = D12438B80ED47AD60857542BE0113ED7 /* Expression.swift */; }; - 3378EE87DA9FB9454669D5D5191B4E98 /* StencilSwiftKit-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F53DDD89903CC6468CD0F552B6F9620C /* StencilSwiftKit-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 33BDE4AC358382F4A99ABE09C41FC9C4 /* CallMacroNodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = D680408E4561AB716D64F6AB22F9FB68 /* CallMacroNodes.swift */; }; - 33D90C9CAF6D9EEC537D8AF319C624C6 /* Parameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = F95B3E1482647F7822F3C47A7AE76BD9 /* Parameters.swift */; }; + 3378EE87DA9FB9454669D5D5191B4E98 /* StencilSwiftKit-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DD3B54D1D2C564D5BA9E996D9CD9883 /* StencilSwiftKit-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 3CFC4A8C135BD9D5BB28AFB16945E761 /* Parameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8454F301FD8C9C5EB0330C86D7159347 /* Parameters.swift */; }; + 4049984A2C747903582DA0EEDBC1C5DD /* StencilSwiftKit-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 81075406C503A904C5D107F68764358A /* StencilSwiftKit-dummy.m */; }; 42E2D5056604852C8C89AE1FCD112B0A /* FilterTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D9976A9FB02F6316003996E10007AEE /* FilterTag.swift */; }; - 4D564D819736B2A614641ABC770C82C1 /* SwiftIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3CE7EC198DBFD800632E7DF1604AD47 /* SwiftIdentifier.swift */; }; + 45C9D21646ED334EA4C9B1DBC549D57E /* Filters+Numbers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9227E56C42EDA867A814F83D87325E4C /* Filters+Numbers.swift */; }; + 486756099E4375C92AEEDD9DBC50C6A6 /* StencilSwiftTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40BFBD138B4E950E8D24A35620CE4CCC /* StencilSwiftTemplate.swift */; }; 5245ABB6A66FF1DEC56583EF468DD7AA /* PathKit-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = C62389B5756FDBA46714335EE5B2079D /* PathKit-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 539BA0FADD1A22A8319F23AC2757AB0A /* SetNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = ADE4751F2E4F5541BF77BAB13BE069CF /* SetNode.swift */; }; 5D5EC19E156C47504B777C0EA9DD7337 /* NowTag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D3CBAF672FD3CA25D7EE1A8E93A6F07 /* NowTag.swift */; }; 5DEF23C8870F6D838AF561730C58977B /* Lexer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31A007C042C580A003C9B6DB5AD1B534 /* Lexer.swift */; }; 6272EE69D3F5DE1DF030E2B979A19909 /* PathKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B85A6D36EC20031BC5814F8D8D514E8 /* PathKit.swift */; }; - 637082FCBAF4D5BA395484A67D546E17 /* Environment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2E92B989035E25169DF9300616F23AAB /* Environment.swift */; }; - 6D1EF02C1F49E85D00EA91EF /* Filters+Strings+Mutations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D1EF02B1F49E85D00EA91EF /* Filters+Strings+Mutations.swift */; }; - 6D1EF0301F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D1EF02F1F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift */; }; - 6D1EF0341F4A25CA00EA91EF /* Filters+Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D1EF0331F4A25CA00EA91EF /* Filters+Strings.swift */; }; + 640F760024085F7314950766AD350F39 /* Filters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C00655023ABE55F6948E0BFBEB532BC /* Filters.swift */; }; + 6B27B2AFB03689DC6884F270293F7C4C /* Filters+Strings+Base.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ACD468B2E8B13C3250DB2C01EE06C5D /* Filters+Strings+Base.swift */; }; + 6D84EE3F1F4C74C5009373F8 /* Filters+Strings+Lettercase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D84EE3D1F4C749E009373F8 /* Filters+Strings+Lettercase.swift */; }; + 6D84EE441F4C7646009373F8 /* Filters+Strings+Boolean.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D84EE401F4C7640009373F8 /* Filters+Strings+Boolean.swift */; }; + 6D84EE451F4C7649009373F8 /* Filters+Strings+Mutations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D84EE411F4C7640009373F8 /* Filters+Strings+Mutations.swift */; }; 722E658DD92366A84D5A67AF0DB0E9C9 /* Context.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8923816ECEE63BE56AD67F2A147EF787 /* Context.swift */; }; - 759D827E105015554B9EEB00299E122C /* MapNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = DFD4D19D5AAB65F338845041B6F767D2 /* MapNode.swift */; }; 77D8C016692C6E24EBEDF607455B0B0E /* PathKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0436538F42B0A2EC1C972F8EE47937E0 /* PathKit.framework */; }; 7C1C25A317F91E37571D91804306D261 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2497E0C37C035DB8276C0C7335E3FC93 /* Cocoa.framework */; }; - 7DEDE215489DFFE058F997C06CD9111D /* Context.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3AAEBD5F3F09F24CD90182ECBC99E81 /* Context.swift */; }; 81990AAD26014F4A7E0106B16808D6F8 /* Loader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2802FBB7965EA4284282522D369C6ECC /* Loader.swift */; }; + 81FFD8D38BC72273CB415EFD68DA80A0 /* CallMacroNodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 396161D6FBC526231F68440FD0F1EA31 /* CallMacroNodes.swift */; }; 82671E88F0AC858A867928AB0088BBFC /* Stencil.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9A68FA9661EC6B4BA5415DDD474F7F00 /* Stencil.framework */; }; 84F6D63C68743A267B4C81F49768A69F /* Include.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5E20637D178539A5F5705320E6AAD3F /* Include.swift */; }; - 85B93ADD2E39D138FCFFBB16141221D7 /* StencilSwiftKit-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 15080A19046B584032439E376D6BD82C /* StencilSwiftKit-dummy.m */; }; 874B546A75EE513B966CCE41CBBA6AD7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2497E0C37C035DB8276C0C7335E3FC93 /* Cocoa.framework */; }; 885DE8DB15D3EA1BA82F5A13E807916E /* Stencil-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B1C96CDE10E0238E81B06BD4DF23DAE /* Stencil-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8BC329E46538413C89622D36F9599D40 /* Filters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C6D246B203676EC17FA9473D97CB418 /* Filters.swift */; }; 9A478B16AE3EE842EDD7634ED3079DC5 /* Variable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17E001094F65D072A6D5E4A0C7F419BD /* Variable.swift */; }; 9BC80B3F2EE018C2BB483457AA07ACFF /* Pods-Tests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 52E08CA96B2F20724148FF5361AD7206 /* Pods-Tests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; A2B9882F7B61B783116C9FF9147D4C05 /* Pods-Tests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = C0ABA9994C05CE2F400945671B7038BA /* Pods-Tests-dummy.m */; }; ADBBBF03C0E4054693087DEC1E0A0D07 /* Filters.swift in Sources */ = {isa = PBXBuildFile; fileRef = C74DCC10F6CC9FB70BEF27A2183A5B4F /* Filters.swift */; }; AE96AD970389A23D2A9177BCBFF6D813 /* Tokenizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FFA7DA1538F3CB30DA2B5074B573E52 /* Tokenizer.swift */; }; - C372EA8DC7AE1A9B3DB7EB2278C29338 /* SetNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5DA2EACBDBA3A368338F5A0A5C89D62D /* SetNode.swift */; }; - C95B8343B8C61222772740E5865B7005 /* Filters+Numbers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02B0A9A1128124B1A17D5AB1E23A0A45 /* Filters+Numbers.swift */; }; + C1E704BAA7D819785010955FCB79F8F2 /* Context.swift in Sources */ = {isa = PBXBuildFile; fileRef = 206ADFB678E7CA238EF565EE3B55327B /* Context.swift */; }; D1E7AA6ADD9E92EBB2117E489B47F62F /* Inheritence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F9B2CC600F3395D308525FD3F495190 /* Inheritence.swift */; }; D58C0117C39AAA28173AB3071A00271D /* Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27AB13C581DBF4D4B41876C69872B183 /* Extension.swift */; }; + DBA7CA786BA538870A7EC7761745E28E /* SwiftIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E16B76DCEF521692FE2B7CE653ED3D9 /* SwiftIdentifier.swift */; }; E436943415A371D33CD28BF20935A2F9 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2497E0C37C035DB8276C0C7335E3FC93 /* Cocoa.framework */; }; - E50716969C524070F2EA8DF037ED4CC2 /* StencilSwiftTemplate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 461150690A6BC561CA3FA50B494C0503 /* StencilSwiftTemplate.swift */; }; F8E0372FF8F02489E3F183B310AA080C /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = B40D2EA1B76284D2E987C4FD200B228E /* Errors.swift */; }; FEC9D11E8431BDABDB06F63BB8E81061 /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DFDC1D3EADE4703881DF92C53FFF464 /* Node.swift */; }; /* End PBXBuildFile section */ @@ -106,76 +106,76 @@ /* Begin PBXFileReference section */ 012306C832DD6A1EBFABB3AFFE57291E /* Stencil-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Stencil-dummy.m"; sourceTree = ""; }; - 02B0A9A1128124B1A17D5AB1E23A0A45 /* Filters+Numbers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Filters+Numbers.swift"; path = "Sources/Filters+Numbers.swift"; sourceTree = ""; }; 0436538F42B0A2EC1C972F8EE47937E0 /* PathKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PathKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 06E5680F77898FA7B456DBF80297AB23 /* Pods-Tests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Tests-frameworks.sh"; sourceTree = ""; }; - 0C6D246B203676EC17FA9473D97CB418 /* Filters.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Filters.swift; path = Sources/Filters.swift; sourceTree = ""; }; 0D3CBAF672FD3CA25D7EE1A8E93A6F07 /* NowTag.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = NowTag.swift; path = Sources/NowTag.swift; sourceTree = ""; }; 0DFDC1D3EADE4703881DF92C53FFF464 /* Node.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Node.swift; path = Sources/Node.swift; sourceTree = ""; }; + 0E16B76DCEF521692FE2B7CE653ED3D9 /* SwiftIdentifier.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftIdentifier.swift; path = Sources/SwiftIdentifier.swift; sourceTree = ""; }; 0F9B2CC600F3395D308525FD3F495190 /* Inheritence.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Inheritence.swift; path = Sources/Inheritence.swift; sourceTree = ""; }; 1143DC189DEAEC4A1278249254968FB1 /* Pods-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Tests.debug.xcconfig"; sourceTree = ""; }; 11F7F2E3F010D24453E40821938EF8EC /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - 15080A19046B584032439E376D6BD82C /* StencilSwiftKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "StencilSwiftKit-dummy.m"; sourceTree = ""; }; 17E001094F65D072A6D5E4A0C7F419BD /* Variable.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Variable.swift; path = Sources/Variable.swift; sourceTree = ""; }; - 1F61A7BE9F20EA077977AF410CCF299C /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 206ADFB678E7CA238EF565EE3B55327B /* Context.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Context.swift; path = Sources/Context.swift; sourceTree = ""; }; 206DA29D6C35E14C93D2BF773A66C54C /* Environment.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Environment.swift; path = Sources/Environment.swift; sourceTree = ""; }; 2155A4AD28DF68375EC10C46F7EDC8AF /* Parser.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Parser.swift; path = Sources/Parser.swift; sourceTree = ""; }; 2497E0C37C035DB8276C0C7335E3FC93 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk/System/Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; }; 27AB13C581DBF4D4B41876C69872B183 /* Extension.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Extension.swift; path = Sources/Extension.swift; sourceTree = ""; }; 2802FBB7965EA4284282522D369C6ECC /* Loader.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Loader.swift; path = Sources/Loader.swift; sourceTree = ""; }; + 2C00655023ABE55F6948E0BFBEB532BC /* Filters.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Filters.swift; path = Sources/Filters.swift; sourceTree = ""; }; 2C8AAD97E22D7F6B08B73B0AE02BFA6D /* Pods-Tests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Tests-resources.sh"; sourceTree = ""; }; 2E6EDE0590FA1A030C93F83C2EEFC65C /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Tests.release.xcconfig"; sourceTree = ""; }; - 2E92B989035E25169DF9300616F23AAB /* Environment.swift */ = {isa = PBXFileReference; includeInIndex = 1; indentWidth = 2; lastKnownFileType = sourcecode.swift; name = Environment.swift; path = Sources/Environment.swift; sourceTree = ""; tabWidth = 2; }; 31A007C042C580A003C9B6DB5AD1B534 /* Lexer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Lexer.swift; path = Sources/Lexer.swift; sourceTree = ""; }; 351D229C0FCFC7B3571671631111EE1C /* Pods_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 396161D6FBC526231F68440FD0F1EA31 /* CallMacroNodes.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CallMacroNodes.swift; path = Sources/CallMacroNodes.swift; sourceTree = ""; }; 3B1C96CDE10E0238E81B06BD4DF23DAE /* Stencil-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Stencil-umbrella.h"; sourceTree = ""; }; 3D9976A9FB02F6316003996E10007AEE /* FilterTag.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FilterTag.swift; path = Sources/FilterTag.swift; sourceTree = ""; }; + 40BFBD138B4E950E8D24A35620CE4CCC /* StencilSwiftTemplate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StencilSwiftTemplate.swift; path = Sources/StencilSwiftTemplate.swift; sourceTree = ""; }; 4309AA7478DD6B254C478AE5335748BA /* Pods-Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Tests-acknowledgements.plist"; sourceTree = ""; }; - 461150690A6BC561CA3FA50B494C0503 /* StencilSwiftTemplate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = StencilSwiftTemplate.swift; path = Sources/StencilSwiftTemplate.swift; sourceTree = ""; }; - 47DB41142F62E8B5174F3DF281DCD5E3 /* Filters+Strings+Boolean.swift */ = {isa = PBXFileReference; includeInIndex = 1; indentWidth = 2; lastKnownFileType = sourcecode.swift; name = "Filters+Strings+Boolean.swift"; path = "Sources/Filters+Strings+Boolean.swift"; sourceTree = ""; tabWidth = 2; }; + 452227FC9CA98E2EE802F569084200C7 /* StencilSwiftKit.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = StencilSwiftKit.xcconfig; sourceTree = ""; }; 49BCF2F8CB8DBEA0E51D00A9DE6AC7F5 /* Stencil.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Stencil.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4ACD468B2E8B13C3250DB2C01EE06C5D /* Filters+Strings+Base.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Filters+Strings+Base.swift"; path = "Sources/Filters+Strings+Base.swift"; sourceTree = ""; }; + 4DD3B54D1D2C564D5BA9E996D9CD9883 /* StencilSwiftKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "StencilSwiftKit-umbrella.h"; sourceTree = ""; }; 4F35C03EE539651D8168B79F18A1DF5B /* Pods-Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-Tests.modulemap"; sourceTree = ""; }; 52E08CA96B2F20724148FF5361AD7206 /* Pods-Tests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Tests-umbrella.h"; sourceTree = ""; }; 5B85A6D36EC20031BC5814F8D8D514E8 /* PathKit.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PathKit.swift; path = Sources/PathKit.swift; sourceTree = ""; }; - 5C8E1A8F9B02B1B71DEA7E55021BAC8A /* StencilSwiftKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "StencilSwiftKit-prefix.pch"; sourceTree = ""; }; - 5DA2EACBDBA3A368338F5A0A5C89D62D /* SetNode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SetNode.swift; path = Sources/SetNode.swift; sourceTree = ""; }; - 5EC97AE8648FE62BB73FAED74FEDA009 /* StencilSwiftKit.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = StencilSwiftKit.xcconfig; sourceTree = ""; }; 69F59D1438D9D791C86016D62F2078B9 /* Template.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Template.swift; path = Sources/Template.swift; sourceTree = ""; }; - 6D1EF02B1F49E85D00EA91EF /* Filters+Strings+Mutations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Filters+Strings+Mutations.swift"; path = "Sources/Filters+Strings+Mutations.swift"; sourceTree = ""; }; - 6D1EF02F1F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Filters+Strings+Lettercase.swift"; path = "Sources/Filters+Strings+Lettercase.swift"; sourceTree = ""; }; - 6D1EF0331F4A25CA00EA91EF /* Filters+Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Filters+Strings.swift"; path = "Sources/Filters+Strings.swift"; sourceTree = ""; }; + 6D84EE3D1F4C749E009373F8 /* Filters+Strings+Lettercase.swift */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.swift; name = "Filters+Strings+Lettercase.swift"; path = "Sources/Filters+Strings+Lettercase.swift"; sourceTree = ""; tabWidth = 2; }; + 6D84EE401F4C7640009373F8 /* Filters+Strings+Boolean.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Filters+Strings+Boolean.swift"; path = "Sources/Filters+Strings+Boolean.swift"; sourceTree = ""; }; + 6D84EE411F4C7640009373F8 /* Filters+Strings+Mutations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Filters+Strings+Mutations.swift"; path = "Sources/Filters+Strings+Mutations.swift"; sourceTree = ""; }; 6E3DE9DADD254D64C598089530A5932B /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 749318FE61E9EC318ED19250766267E2 /* Stencil-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Stencil-prefix.pch"; sourceTree = ""; }; 7DB310C86ADAE310E9DF111FDD487FAF /* StencilSwiftKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StencilSwiftKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 81075406C503A904C5D107F68764358A /* StencilSwiftKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "StencilSwiftKit-dummy.m"; sourceTree = ""; }; + 8454F301FD8C9C5EB0330C86D7159347 /* Parameters.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Parameters.swift; path = Sources/Parameters.swift; sourceTree = ""; }; 8923816ECEE63BE56AD67F2A147EF787 /* Context.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Context.swift; path = Sources/Context.swift; sourceTree = ""; }; + 89406CF74F5F8BA2BEE26EBB7E7F1FFA /* Environment.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Environment.swift; path = Sources/Environment.swift; sourceTree = ""; }; 8CA49A25561E541E61395E8C64512F22 /* PathKit-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PathKit-dummy.m"; sourceTree = ""; }; 8CCB7B571DD30214319D05B2A2D01268 /* ForTag.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ForTag.swift; path = Sources/ForTag.swift; sourceTree = ""; }; 8FFA7DA1538F3CB30DA2B5074B573E52 /* Tokenizer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Tokenizer.swift; path = Sources/Tokenizer.swift; sourceTree = ""; }; 919EAEDB009B1AA70C305AC91847AC41 /* PathKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = PathKit.modulemap; sourceTree = ""; }; + 9227E56C42EDA867A814F83D87325E4C /* Filters+Numbers.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "Filters+Numbers.swift"; path = "Sources/Filters+Numbers.swift"; sourceTree = ""; }; 93A3BA06E90B797B9126411EF449E61E /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 9A68FA9661EC6B4BA5415DDD474F7F00 /* Stencil.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Stencil.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A32A857A363E334B4FF67BDFE4B320E8 /* StencilSwiftKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "StencilSwiftKit-prefix.pch"; sourceTree = ""; }; A5E20637D178539A5F5705320E6AAD3F /* Include.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Include.swift; path = Sources/Include.swift; sourceTree = ""; }; + ADE4751F2E4F5541BF77BAB13BE069CF /* SetNode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SetNode.swift; path = Sources/SetNode.swift; sourceTree = ""; }; B0A2858DB038304C5239C4738D8E3643 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - B3AAEBD5F3F09F24CD90182ECBC99E81 /* Context.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Context.swift; path = Sources/Context.swift; sourceTree = ""; }; B40D2EA1B76284D2E987C4FD200B228E /* Errors.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Errors.swift; path = Sources/Errors.swift; sourceTree = ""; }; B51EE1F2CACBC9829B2FEC2985DEA9D2 /* Stencil.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Stencil.xcconfig; sourceTree = ""; }; + B985FA864B5D545D8567C64485D9F9D2 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; BFE531A4BA3F8D5F7B6C9BD6D217DA29 /* Pods-Tests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Tests-acknowledgements.markdown"; sourceTree = ""; }; C0ABA9994C05CE2F400945671B7038BA /* Pods-Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Tests-dummy.m"; sourceTree = ""; }; C1E8657D8A2E60CA5179FDE94F283B2A /* PathKit.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PathKit.xcconfig; sourceTree = ""; }; - C3CE7EC198DBFD800632E7DF1604AD47 /* SwiftIdentifier.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftIdentifier.swift; path = Sources/SwiftIdentifier.swift; sourceTree = ""; }; + C58F57104A480134D785C5B0D14A7DE7 /* MapNode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MapNode.swift; path = Sources/MapNode.swift; sourceTree = ""; }; C62389B5756FDBA46714335EE5B2079D /* PathKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PathKit-umbrella.h"; sourceTree = ""; }; C68D522B00371B910EC16028EBD47384 /* PathKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PathKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C74DCC10F6CC9FB70BEF27A2183A5B4F /* Filters.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Filters.swift; path = Sources/Filters.swift; sourceTree = ""; }; D12438B80ED47AD60857542BE0113ED7 /* Expression.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Expression.swift; path = Sources/Expression.swift; sourceTree = ""; }; + D4A02F7D17B5E62F478855B7892B7F00 /* StencilSwiftKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = StencilSwiftKit.modulemap; sourceTree = ""; }; D5846CC8D36C9B97B51ACC82399D6A12 /* PathKit-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PathKit-prefix.pch"; sourceTree = ""; }; - D680408E4561AB716D64F6AB22F9FB68 /* CallMacroNodes.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CallMacroNodes.swift; path = Sources/CallMacroNodes.swift; sourceTree = ""; }; D6C2D28B3980163C3F38852C8437E5C2 /* Stencil.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = Stencil.modulemap; sourceTree = ""; }; D887BD539929925B9535E5136F861F20 /* IfTag.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = IfTag.swift; path = Sources/IfTag.swift; sourceTree = ""; }; - DFD4D19D5AAB65F338845041B6F767D2 /* MapNode.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = MapNode.swift; path = Sources/MapNode.swift; sourceTree = ""; }; - E9C51D01C292146479413F2582CA6927 /* StencilSwiftKit.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = StencilSwiftKit.modulemap; sourceTree = ""; }; - F53DDD89903CC6468CD0F552B6F9620C /* StencilSwiftKit-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "StencilSwiftKit-umbrella.h"; sourceTree = ""; }; - F95B3E1482647F7822F3C47A7AE76BD9 /* Parameters.swift */ = {isa = PBXFileReference; includeInIndex = 1; indentWidth = 2; lastKnownFileType = sourcecode.swift; name = Parameters.swift; path = Sources/Parameters.swift; sourceTree = ""; tabWidth = 2; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -226,28 +226,22 @@ name = "Targets Support Files"; sourceTree = ""; }; - 1F5E5F8A51A1DB712AA69F86066566AE /* Frameworks */ = { + 1158BA44BE3661F97F4E5A0D116BDFAD /* Development Pods */ = { isa = PBXGroup; children = ( - 0436538F42B0A2EC1C972F8EE47937E0 /* PathKit.framework */, - 9A68FA9661EC6B4BA5415DDD474F7F00 /* Stencil.framework */, - BAD0DD2B62009F64C32E0A3BDCACD5FB /* OS X */, + EB28C4CDEC19AE1FE4423075FE098234 /* StencilSwiftKit */, ); - name = Frameworks; + name = "Development Pods"; sourceTree = ""; }; - 36E1E19AEC7388FCFE984D30FC2ECBD5 /* Support Files */ = { + 1F5E5F8A51A1DB712AA69F86066566AE /* Frameworks */ = { isa = PBXGroup; children = ( - 1F61A7BE9F20EA077977AF410CCF299C /* Info.plist */, - E9C51D01C292146479413F2582CA6927 /* StencilSwiftKit.modulemap */, - 5EC97AE8648FE62BB73FAED74FEDA009 /* StencilSwiftKit.xcconfig */, - 15080A19046B584032439E376D6BD82C /* StencilSwiftKit-dummy.m */, - 5C8E1A8F9B02B1B71DEA7E55021BAC8A /* StencilSwiftKit-prefix.pch */, - F53DDD89903CC6468CD0F552B6F9620C /* StencilSwiftKit-umbrella.h */, + 0436538F42B0A2EC1C972F8EE47937E0 /* PathKit.framework */, + 9A68FA9661EC6B4BA5415DDD474F7F00 /* Stencil.framework */, + BAD0DD2B62009F64C32E0A3BDCACD5FB /* OS X */, ); - name = "Support Files"; - path = "Pods/Target Support Files/StencilSwiftKit"; + name = Frameworks; sourceTree = ""; }; 47034B618C7AB6B73C31D4C6B5F235F8 /* Pods-Tests */ = { @@ -282,14 +276,6 @@ path = "../Target Support Files/Stencil"; sourceTree = ""; }; - 5E27F84F0FEB7FB724174B2BE67CEDCE /* Development Pods */ = { - isa = PBXGroup; - children = ( - EDCB12D1555E3A866ECE71D44792EDBD /* StencilSwiftKit */, - ); - name = "Development Pods"; - sourceTree = ""; - }; 6724D708D9DFD7974FF62943F623BFBB /* Pods */ = { isa = PBXGroup; children = ( @@ -317,7 +303,7 @@ isa = PBXGroup; children = ( 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, - 5E27F84F0FEB7FB724174B2BE67CEDCE /* Development Pods */, + 1158BA44BE3661F97F4E5A0D116BDFAD /* Development Pods */, 1F5E5F8A51A1DB712AA69F86066566AE /* Frameworks */, 6724D708D9DFD7974FF62943F623BFBB /* Pods */, B499EA03E3E7FF8D31B3BE631B1240D0 /* Products */, @@ -381,24 +367,38 @@ name = "OS X"; sourceTree = ""; }; - EDCB12D1555E3A866ECE71D44792EDBD /* StencilSwiftKit */ = { + C617FEEEE496ACCB578760C97CB192AE /* Support Files */ = { isa = PBXGroup; children = ( - D680408E4561AB716D64F6AB22F9FB68 /* CallMacroNodes.swift */, - B3AAEBD5F3F09F24CD90182ECBC99E81 /* Context.swift */, - 2E92B989035E25169DF9300616F23AAB /* Environment.swift */, - 0C6D246B203676EC17FA9473D97CB418 /* Filters.swift */, - 02B0A9A1128124B1A17D5AB1E23A0A45 /* Filters+Numbers.swift */, - 6D1EF02F1F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift */, - 6D1EF02B1F49E85D00EA91EF /* Filters+Strings+Mutations.swift */, - 47DB41142F62E8B5174F3DF281DCD5E3 /* Filters+Strings+Boolean.swift */, - 6D1EF0331F4A25CA00EA91EF /* Filters+Strings.swift */, - DFD4D19D5AAB65F338845041B6F767D2 /* MapNode.swift */, - F95B3E1482647F7822F3C47A7AE76BD9 /* Parameters.swift */, - 5DA2EACBDBA3A368338F5A0A5C89D62D /* SetNode.swift */, - 461150690A6BC561CA3FA50B494C0503 /* StencilSwiftTemplate.swift */, - C3CE7EC198DBFD800632E7DF1604AD47 /* SwiftIdentifier.swift */, - 36E1E19AEC7388FCFE984D30FC2ECBD5 /* Support Files */, + B985FA864B5D545D8567C64485D9F9D2 /* Info.plist */, + D4A02F7D17B5E62F478855B7892B7F00 /* StencilSwiftKit.modulemap */, + 452227FC9CA98E2EE802F569084200C7 /* StencilSwiftKit.xcconfig */, + 81075406C503A904C5D107F68764358A /* StencilSwiftKit-dummy.m */, + A32A857A363E334B4FF67BDFE4B320E8 /* StencilSwiftKit-prefix.pch */, + 4DD3B54D1D2C564D5BA9E996D9CD9883 /* StencilSwiftKit-umbrella.h */, + ); + name = "Support Files"; + path = "Pods/Target Support Files/StencilSwiftKit"; + sourceTree = ""; + }; + EB28C4CDEC19AE1FE4423075FE098234 /* StencilSwiftKit */ = { + isa = PBXGroup; + children = ( + 4ACD468B2E8B13C3250DB2C01EE06C5D /* Filters+Strings+Base.swift */, + 6D84EE401F4C7640009373F8 /* Filters+Strings+Boolean.swift */, + 6D84EE411F4C7640009373F8 /* Filters+Strings+Mutations.swift */, + 6D84EE3D1F4C749E009373F8 /* Filters+Strings+Lettercase.swift */, + 396161D6FBC526231F68440FD0F1EA31 /* CallMacroNodes.swift */, + 206ADFB678E7CA238EF565EE3B55327B /* Context.swift */, + 89406CF74F5F8BA2BEE26EBB7E7F1FFA /* Environment.swift */, + 2C00655023ABE55F6948E0BFBEB532BC /* Filters.swift */, + 9227E56C42EDA867A814F83D87325E4C /* Filters+Numbers.swift */, + C58F57104A480134D785C5B0D14A7DE7 /* MapNode.swift */, + 8454F301FD8C9C5EB0330C86D7159347 /* Parameters.swift */, + ADE4751F2E4F5541BF77BAB13BE069CF /* SetNode.swift */, + 40BFBD138B4E950E8D24A35620CE4CCC /* StencilSwiftTemplate.swift */, + 0E16B76DCEF521692FE2B7CE653ED3D9 /* SwiftIdentifier.swift */, + C617FEEEE496ACCB578760C97CB192AE /* Support Files */, ); name = StencilSwiftKit; path = ..; @@ -501,7 +501,7 @@ isa = PBXNativeTarget; buildConfigurationList = 129C5DBD1F855F49F876BF6123ACCEA1 /* Build configuration list for PBXNativeTarget "StencilSwiftKit" */; buildPhases = ( - F69C2FA52CC9C8802CF4C17A1E2BA0FF /* Sources */, + 220423BDC70FA11EDD707B0C85EA6D41 /* Sources */, 0F3EB15820713BB45F78D235C5EDFAB9 /* Frameworks */, D69B46456E4A5977AF2F2E41E1569930 /* Headers */, ); @@ -573,42 +573,42 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 5FCA4CE5597481B9D6D11D12673C7E41 /* Sources */ = { + 220423BDC70FA11EDD707B0C85EA6D41 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 040B29D0120B5B450B98FC67FEC958B8 /* PathKit-dummy.m in Sources */, - 6272EE69D3F5DE1DF030E2B979A19909 /* PathKit.swift in Sources */, + 81FFD8D38BC72273CB415EFD68DA80A0 /* CallMacroNodes.swift in Sources */, + C1E704BAA7D819785010955FCB79F8F2 /* Context.swift in Sources */, + 2CBF2B3563EE7F6006A506310244966A /* Environment.swift in Sources */, + 45C9D21646ED334EA4C9B1DBC549D57E /* Filters+Numbers.swift in Sources */, + 6B27B2AFB03689DC6884F270293F7C4C /* Filters+Strings+Base.swift in Sources */, + 6D84EE451F4C7649009373F8 /* Filters+Strings+Mutations.swift in Sources */, + 6D84EE441F4C7646009373F8 /* Filters+Strings+Boolean.swift in Sources */, + 6D84EE3F1F4C74C5009373F8 /* Filters+Strings+Lettercase.swift in Sources */, + 640F760024085F7314950766AD350F39 /* Filters.swift in Sources */, + 25133010A93E9FE79DD02F53F12C26D2 /* MapNode.swift in Sources */, + 3CFC4A8C135BD9D5BB28AFB16945E761 /* Parameters.swift in Sources */, + 539BA0FADD1A22A8319F23AC2757AB0A /* SetNode.swift in Sources */, + 4049984A2C747903582DA0EEDBC1C5DD /* StencilSwiftKit-dummy.m in Sources */, + 486756099E4375C92AEEDD9DBC50C6A6 /* StencilSwiftTemplate.swift in Sources */, + DBA7CA786BA538870A7EC7761745E28E /* SwiftIdentifier.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - ED7F721EA5274D6B4F54972B473CC719 /* Sources */ = { + 5FCA4CE5597481B9D6D11D12673C7E41 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - A2B9882F7B61B783116C9FF9147D4C05 /* Pods-Tests-dummy.m in Sources */, + 040B29D0120B5B450B98FC67FEC958B8 /* PathKit-dummy.m in Sources */, + 6272EE69D3F5DE1DF030E2B979A19909 /* PathKit.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - F69C2FA52CC9C8802CF4C17A1E2BA0FF /* Sources */ = { + ED7F721EA5274D6B4F54972B473CC719 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 33BDE4AC358382F4A99ABE09C41FC9C4 /* CallMacroNodes.swift in Sources */, - 7DEDE215489DFFE058F997C06CD9111D /* Context.swift in Sources */, - 637082FCBAF4D5BA395484A67D546E17 /* Environment.swift in Sources */, - C95B8343B8C61222772740E5865B7005 /* Filters+Numbers.swift in Sources */, - 6D1EF0341F4A25CA00EA91EF /* Filters+Strings.swift in Sources */, - 6D1EF02C1F49E85D00EA91EF /* Filters+Strings+Mutations.swift in Sources */, - 261ED3A17531A5012E5E2EA78BC189C3 /* Filters+Strings+Boolean.swift in Sources */, - 6D1EF0301F49EC7C00EA91EF /* Filters+Strings+Lettercase.swift in Sources */, - 8BC329E46538413C89622D36F9599D40 /* Filters.swift in Sources */, - 759D827E105015554B9EEB00299E122C /* MapNode.swift in Sources */, - 33D90C9CAF6D9EEC537D8AF319C624C6 /* Parameters.swift in Sources */, - C372EA8DC7AE1A9B3DB7EB2278C29338 /* SetNode.swift in Sources */, - 85B93ADD2E39D138FCFFBB16141221D7 /* StencilSwiftKit-dummy.m in Sources */, - E50716969C524070F2EA8DF037ED4CC2 /* StencilSwiftTemplate.swift in Sources */, - 4D564D819736B2A614641ABC770C82C1 /* SwiftIdentifier.swift in Sources */, + A2B9882F7B61B783116C9FF9147D4C05 /* Pods-Tests-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -749,7 +749,7 @@ }; 2DD46580A7EF8CF0A97B1115C3549D48 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5EC97AE8648FE62BB73FAED74FEDA009 /* StencilSwiftKit.xcconfig */; + baseConfigurationReference = 452227FC9CA98E2EE802F569084200C7 /* StencilSwiftKit.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = "-"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; @@ -972,7 +972,7 @@ }; 9E4CBD963109B9015F7FEEBC006EE5A3 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5EC97AE8648FE62BB73FAED74FEDA009 /* StencilSwiftKit.xcconfig */; + baseConfigurationReference = 452227FC9CA98E2EE802F569084200C7 /* StencilSwiftKit.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = "-"; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; diff --git a/Sources/Filters+Strings.swift b/Sources/Filters+Strings+Base.swift similarity index 100% rename from Sources/Filters+Strings.swift rename to Sources/Filters+Strings+Base.swift diff --git a/Sources/Filters+Strings+Lettercase.swift b/Sources/Filters+Strings+Lettercase.swift index 73817d5f..d2272641 100644 --- a/Sources/Filters+Strings+Lettercase.swift +++ b/Sources/Filters+Strings+Lettercase.swift @@ -8,152 +8,152 @@ import Foundation import Stencil extension Filters.Strings { - /// Lowers the first letter of the string - /// e.g. "People picker" gives "people picker", "Sports Stats" gives "sports Stats" - static func lowerFirstLetter(_ value: Any?) throws -> Any? { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - let first = String(string.characters.prefix(1)).lowercased() - let other = String(string.characters.dropFirst(1)) - return first + other - } + /// Lowers the first letter of the string + /// e.g. "People picker" gives "people picker", "Sports Stats" gives "sports Stats" + static func lowerFirstLetter(_ value: Any?) throws -> Any? { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + let first = String(string.characters.prefix(1)).lowercased() + let other = String(string.characters.dropFirst(1)) + return first + other + } - /// If the string starts with only one uppercase letter, lowercase that first letter - /// If the string starts with multiple uppercase letters, lowercase those first letters - /// up to the one before the last uppercase one, but only if the last one is followed by - /// a lowercase character. - /// e.g. "PeoplePicker" gives "peoplePicker" but "URLChooser" gives "urlChooser" - static func lowerFirstWord(_ value: Any?) throws -> Any? { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - let cs = CharacterSet.uppercaseLetters - let scalars = string.unicodeScalars - let start = scalars.startIndex - var idx = start - while let scalar = UnicodeScalar(scalars[idx].value), cs.contains(scalar) && idx <= scalars.endIndex { - idx = scalars.index(after: idx) - } - if idx > scalars.index(after: start) && idx < scalars.endIndex, - let scalar = UnicodeScalar(scalars[idx].value), - CharacterSet.lowercaseLetters.contains(scalar) { - idx = scalars.index(before: idx) - } - let transformed = String(scalars[start.. Any? { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + let cs = CharacterSet.uppercaseLetters + let scalars = string.unicodeScalars + let start = scalars.startIndex + var idx = start + while let scalar = UnicodeScalar(scalars[idx].value), cs.contains(scalar) && idx <= scalars.endIndex { + idx = scalars.index(after: idx) } - - /// Uppers the first letter of the string - /// e.g. "people picker" gives "People picker", "sports Stats" gives "Sports Stats" - /// - /// - Parameters: - /// - value: the value to uppercase first letter of - /// - arguments: the arguments to the function; expecting zero - /// - Returns: the string with first letter being uppercased - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string - static func upperFirstLetter(_ value: Any?) throws -> Any? { - guard let string = value as? String else { throw Filters.Error.invalidInputType } - return upperFirstLetter(string) + if idx > scalars.index(after: start) && idx < scalars.endIndex, + let scalar = UnicodeScalar(scalars[idx].value), + CharacterSet.lowercaseLetters.contains(scalar) { + idx = scalars.index(before: idx) } + let transformed = String(scalars[start.. Any? { - let stripLeading = try Filters.parseBool(from: arguments, required: false) ?? false - guard let string = value as? String else { throw Filters.Error.invalidInputType } + /// Uppers the first letter of the string + /// e.g. "people picker" gives "People picker", "sports Stats" gives "Sports Stats" + /// + /// - Parameters: + /// - value: the value to uppercase first letter of + /// - arguments: the arguments to the function; expecting zero + /// - Returns: the string with first letter being uppercased + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string + static func upperFirstLetter(_ value: Any?) throws -> Any? { + guard let string = value as? String else { throw Filters.Error.invalidInputType } + return upperFirstLetter(string) + } - return try snakeToCamelCase(string, stripLeading: stripLeading) - } + /// Converts snake_case to camelCase. Takes an optional Bool argument for removing any resulting + /// leading '_' characters, which defaults to false + /// + /// - Parameters: + /// - value: the value to be processed + /// - arguments: the arguments to the function; expecting zero or one boolean argument + /// - Returns: the camel case string + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string + static func snakeToCamelCase(_ value: Any?, arguments: [Any?]) throws -> Any? { + let stripLeading = try Filters.parseBool(from: arguments, required: false) ?? false + guard let string = value as? String else { throw Filters.Error.invalidInputType } - /// Converts camelCase to snake_case. Takes an optional Bool argument for making the string lower case, - /// which defaults to true - /// - /// - Parameters: - /// - value: the value to be processed - /// - arguments: the arguments to the function; expecting zero or one boolean argument - /// - Returns: the snake case string - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string - static func camelToSnakeCase(_ value: Any?, arguments: [Any?]) throws -> Any? { - let toLower = try Filters.parseBool(from: arguments, required: false) ?? true - guard let string = value as? String else { throw Filters.Error.invalidInputType } + return try snakeToCamelCase(string, stripLeading: stripLeading) + } - let snakeCase = try snakecase(string) - if toLower { - return snakeCase.lowercased() - } - return snakeCase + /// Converts camelCase to snake_case. Takes an optional Bool argument for making the string lower case, + /// which defaults to true + /// + /// - Parameters: + /// - value: the value to be processed + /// - arguments: the arguments to the function; expecting zero or one boolean argument + /// - Returns: the snake case string + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string + static func camelToSnakeCase(_ value: Any?, arguments: [Any?]) throws -> Any? { + let toLower = try Filters.parseBool(from: arguments, required: false) ?? true + guard let string = value as? String else { throw Filters.Error.invalidInputType } + + let snakeCase = try snakecase(string) + if toLower { + return snakeCase.lowercased() } + return snakeCase + } - /// Converts snake_case to camelCase, stripping prefix underscores if needed - /// - /// - Parameters: - /// - string: the value to be processed - /// - stripLeading: if false, will preserve leading underscores - /// - Returns: the camel case string - static func snakeToCamelCase(_ string: String, stripLeading: Bool) throws -> String { - let unprefixed: String - if try containsAnyLowercasedChar(string) { - let comps = string.components(separatedBy: "_") - unprefixed = comps.map { upperFirstLetter($0) }.joined(separator: "") - } else { - let comps = try snakecase(string).components(separatedBy: "_") - unprefixed = comps.map { $0.capitalized }.joined(separator: "") - } + /// Converts snake_case to camelCase, stripping prefix underscores if needed + /// + /// - Parameters: + /// - string: the value to be processed + /// - stripLeading: if false, will preserve leading underscores + /// - Returns: the camel case string + static func snakeToCamelCase(_ string: String, stripLeading: Bool) throws -> String { + let unprefixed: String + if try containsAnyLowercasedChar(string) { + let comps = string.components(separatedBy: "_") + unprefixed = comps.map { upperFirstLetter($0) }.joined(separator: "") + } else { + let comps = try snakecase(string).components(separatedBy: "_") + unprefixed = comps.map { $0.capitalized }.joined(separator: "") + } - // only if passed true, strip the prefix underscores - var prefixUnderscores = "" - var result: String { return prefixUnderscores + unprefixed } - if stripLeading { - return result - } - for scalar in string.unicodeScalars { - guard scalar == "_" else { break } - prefixUnderscores += "_" - } + // only if passed true, strip the prefix underscores + var prefixUnderscores = "" + var result: String { return prefixUnderscores + unprefixed } + if stripLeading { return result } + for scalar in string.unicodeScalars { + guard scalar == "_" else { break } + prefixUnderscores += "_" + } + return result + } - // MARK: - Private + // MARK: - Private - private static func containsAnyLowercasedChar(_ string: String) throws -> Bool { - let lowercaseCharRegex = try NSRegularExpression(pattern: "[a-z]", options: .dotMatchesLineSeparators) - let fullRange = NSRange(location: 0, length: string.unicodeScalars.count) - return lowercaseCharRegex.firstMatch(in: string, options: .reportCompletion, range: fullRange) != nil - } + private static func containsAnyLowercasedChar(_ string: String) throws -> Bool { + let lowercaseCharRegex = try NSRegularExpression(pattern: "[a-z]", options: .dotMatchesLineSeparators) + let fullRange = NSRange(location: 0, length: string.unicodeScalars.count) + return lowercaseCharRegex.firstMatch(in: string, options: .reportCompletion, range: fullRange) != nil + } - /// Uppers the first letter of the string - /// e.g. "people picker" gives "People picker", "sports Stats" gives "Sports Stats" - /// - /// - Parameters: - /// - value: the value to uppercase first letter of - /// - arguments: the arguments to the function; expecting zero - /// - Returns: the string with first letter being uppercased - /// - Throws: FilterError.invalidInputType if the value parameter isn't a string - private static func upperFirstLetter(_ value: String) -> String { - guard let first = value.unicodeScalars.first else { return value } - return String(first).uppercased() + String(value.unicodeScalars.dropFirst()) - } + /// Uppers the first letter of the string + /// e.g. "people picker" gives "People picker", "sports Stats" gives "Sports Stats" + /// + /// - Parameters: + /// - value: the value to uppercase first letter of + /// - arguments: the arguments to the function; expecting zero + /// - Returns: the string with first letter being uppercased + /// - Throws: FilterError.invalidInputType if the value parameter isn't a string + private static func upperFirstLetter(_ value: String) -> String { + guard let first = value.unicodeScalars.first else { return value } + return String(first).uppercased() + String(value.unicodeScalars.dropFirst()) + } - /// This returns the snake cased variant of the string. - /// - /// - Parameter string: The string to snake_case - /// - Returns: The string snake cased from either snake_cased or camelCased string. - private static func snakecase(_ string: String) throws -> String { - let longUpper = try NSRegularExpression(pattern: "([A-Z\\d]+)([A-Z][a-z])", options: .dotMatchesLineSeparators) - let camelCased = try NSRegularExpression(pattern: "([a-z\\d])([A-Z])", options: .dotMatchesLineSeparators) + /// This returns the snake cased variant of the string. + /// + /// - Parameter string: The string to snake_case + /// - Returns: The string snake cased from either snake_cased or camelCased string. + private static func snakecase(_ string: String) throws -> String { + let longUpper = try NSRegularExpression(pattern: "([A-Z\\d]+)([A-Z][a-z])", options: .dotMatchesLineSeparators) + let camelCased = try NSRegularExpression(pattern: "([a-z\\d])([A-Z])", options: .dotMatchesLineSeparators) - let fullRange = NSRange(location: 0, length: string.unicodeScalars.count) - var result = longUpper.stringByReplacingMatches(in: string, - options: .reportCompletion, - range: fullRange, - withTemplate: "$1_$2") - result = camelCased.stringByReplacingMatches(in: result, - options: .reportCompletion, - range: fullRange, - withTemplate: "$1_$2") - return result.replacingOccurrences(of: "-", with: "_") - } + let fullRange = NSRange(location: 0, length: string.unicodeScalars.count) + var result = longUpper.stringByReplacingMatches(in: string, + options: .reportCompletion, + range: fullRange, + withTemplate: "$1_$2") + result = camelCased.stringByReplacingMatches(in: result, + options: .reportCompletion, + range: fullRange, + withTemplate: "$1_$2") + return result.replacingOccurrences(of: "-", with: "_") + } }