diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 201ff1434..2c76d3ffb 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -12,28 +12,13 @@ jobs: runs-on: macos-14-xlarge steps: - - name: Checkout - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + - uses: jdx/mise-action@v2 - - name: Read env - run: cat .github/workflows/env.properties >> $GITHUB_ENV + - name: Run swiftformat + run: swiftformat --lint . - - name: Switch to Xcode ${{ env.xcode_version }} - run: sudo xcode-select -s /Applications/Xcode_${{ env.xcode_version }}.app - - - name: Cache SPM build - uses: actions/cache@v2 - with: - path: .build - key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }} - restore-keys: | - ${{ runner.os }}-spm- - - - name: Run SwiftFormat - run: | - swift run -c release swiftformat --lint . - - - name: Report error - if: ${{ failure() }} - run: | - echo '::error::SwiftFormat linting failed. Run `Scripts/swiftformat` to format your code.' + - name: Report error + if: ${{ failure() }} + run: | + echo '::error::SwiftFormat linting failed. Run `Scripts/swiftformat` to format your code.' diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 2ac73dd31..353c7c73e 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -12,26 +12,31 @@ jobs: runs-on: macos-14-xlarge + env: + TUIST_TEST_DEVICE: iPhone SE (3rd generation) + TUIST_TEST_PLATFORM: iOS + strategy: fail-fast: false # Don’t fail-fast so that we get all snapshot test changes matrix: include: - sdk: "15.4" - destination: platform=iOS Simulator,OS=15.4,name=iPhone SE (3rd generation) + simctl_runtime: "com.apple.CoreSimulator.SimRuntime.iOS-15-4" installation_required: true - sdk: "16.2" - destination: platform=iOS Simulator,OS=16.2,name=iPhone SE (3rd generation) + simctl_runtime: "com.apple.CoreSimulator.SimRuntime.iOS-16-2" installation_required: true - sdk: "17.2" - destination: platform=iOS Simulator,OS=17.2,name=iPhone SE (3rd generation) + simctl_runtime: "com.apple.CoreSimulator.SimRuntime.iOS-17-2" # The iOS 17.2 SDK is pre-installed on the macOS 13 image. # Attempting to install it will fail with an error. installation_required: false steps: - uses: actions/checkout@v4 + - uses: jdx/mise-action@v2 - name: Read env run: cat .github/workflows/env.properties >> $GITHUB_ENV @@ -46,9 +51,18 @@ jobs: if: ${{ matrix.installation_required }} run: sudo xcodes runtimes install "iOS ${{ matrix.sdk }}" - - name: Build & Test + - name: Ensure sim exists run: | - xcodebuild -scheme "BlueprintUI-Package" -destination "${{ matrix.destination }}" build test + xcrun simctl create \ + "${{ env.TUIST_TEST_DEVICE }}" \ + "${{ env.TUIST_TEST_DEVICE }}" \ + "${{ matrix.simctl_runtime }}" + + - name: Install dependencies + run: tuist install --path SampleApp + + - name: Build & Test + run: tuist test --path SampleApp --os ${{ matrix.sdk }} UnitTests - name: Package snapshot changes if: ${{ failure() }} @@ -61,32 +75,3 @@ jobs: with: name: snapshot_changes_${{ matrix.sdk }} path: snapshot_changes_${{ matrix.sdk }}.tar - - - cocoapods: - name: "CocoaPods" - - runs-on: macos-14-xlarge - - steps: - - uses: actions/checkout@v4 - - - name: Read env - run: cat .github/workflows/env.properties >> $GITHUB_ENV - - - name: Switch to Xcode ${{ env.xcode_version }} - run: sudo xcode-select -s /Applications/Xcode_${{ env.xcode_version }}.app - - - name: Setup Ruby - uses: ruby/setup-ruby@v1 - with: - # Uses version specified in .ruby_version - bundler-cache: true # runs 'bundle install' and caches installed gems automatically - - - name: Pod Install - run: | - bundle exec pod install --project-directory=SampleApp/ - - - name: Build & Test - run: | - xcodebuild -workspace SampleApp/SampleApp.xcworkspace -scheme "BlueprintUI-Unit-Tests" -destination "platform=iOS Simulator,OS=17.2,name=iPhone SE (3rd generation)" diff --git a/.gitignore b/.gitignore index b5d85db42..d7abe8831 100644 --- a/.gitignore +++ b/.gitignore @@ -24,10 +24,17 @@ Pods/ # .swiftpm/ .build/ -BlueprintUI.xcodeproj/ # jazzy .docs/ # User settings .vscode/ + +# Tuist +/Derived +/*.xcodeproj +/*.xcworkspace +/SampleApp/Derived +/SampleApp/*.xcodeproj +/SampleApp/*.xcworkspace diff --git a/.hooks/pre-commit b/.hooks/pre-commit index 418d52bbb..cebe18d56 100755 --- a/.hooks/pre-commit +++ b/.hooks/pre-commit @@ -5,7 +5,13 @@ if [[ $(git rev-parse -q --verify MERGE_HEAD) ]]; then exit 0 fi -git diff --diff-filter=d --staged --name-only | grep -e ".swift$" | while read file; do - swift run -c release swiftformat "${file}"; - git add "$file"; -done +ROOT="$(git rev-parse --show-toplevel)" +SWIFT_FORMAT="mise x -- swiftformat" +GIT_FORMAT_STAGED="$ROOT/Scripts/git-format-staged" +CONFIG="${ROOT}/.swiftformat" + +$SWIFT_FORMAT --version 1>/dev/null 2>&1 +if [ $? -eq 0 ] +then + $GIT_FORMAT_STAGED --formatter "$SWIFT_FORMAT stdin --config "$CONFIG" --stdinpath '{}'" "*.swift" +fi diff --git a/.mise.toml b/.mise.toml new file mode 100644 index 000000000..ad6f21f9c --- /dev/null +++ b/.mise.toml @@ -0,0 +1,7 @@ +[tools] +tuist = "4.23.0" +swiftformat = "0.54.2" + +[settings] +# do not try to read versions from .nvmrc, .ruby-version, etc. +legacy_version_file = false diff --git a/BlueprintUI/Sources/AttributedText/TextAttributeContainer.swift b/BlueprintUI/Sources/AttributedText/TextAttributeContainer.swift index 7472593e1..c48a4ed1a 100644 --- a/BlueprintUI/Sources/AttributedText/TextAttributeContainer.swift +++ b/BlueprintUI/Sources/AttributedText/TextAttributeContainer.swift @@ -18,9 +18,9 @@ public struct TextAttributeContainer { public subscript(key: Key.Type) -> Key.Value? where Key: AttributedTextKey { get { if let value = storage[key.name] as? Key.Value { - return value + value } else { - return nil + nil } } set { diff --git a/BlueprintUI/Sources/BlueprintView/BlueprintView.swift b/BlueprintUI/Sources/BlueprintView/BlueprintView.swift index 94ec5cccf..1f5eb3c79 100644 --- a/BlueprintUI/Sources/BlueprintView/BlueprintView.swift +++ b/BlueprintUI/Sources/BlueprintView/BlueprintView.swift @@ -303,9 +303,9 @@ public final class BlueprintView: UIView { func constraint() -> SizeConstraint { if bounds.width == 0 { - return .unconstrained + .unconstrained } else { - return .init(width: bounds.width) + .init(width: bounds.width) } } @@ -517,9 +517,9 @@ public final class BlueprintView: UIView { self.automaticallyInheritsEnvironmentFromContainingBlueprintViews, let inherited = self.inheritedBlueprintEnvironment { - return inherited + inherited } else { - return .empty + .empty } }() diff --git a/BlueprintUI/Sources/BlueprintView/ElementPreview.swift b/BlueprintUI/Sources/BlueprintView/ElementPreview.swift index 46802d153..69fa92e63 100644 --- a/BlueprintUI/Sources/BlueprintView/ElementPreview.swift +++ b/BlueprintUI/Sources/BlueprintView/ElementPreview.swift @@ -131,10 +131,10 @@ public struct ElementPreview: View { // MARK: View public var body: some View { - ForEach(self.previewTypes, id: \.identifier) { previewType in + ForEach(previewTypes, id: \.identifier) { previewType in previewType.previewView( - with: self.name, - for: self.provider() + with: name, + for: provider() ) } } @@ -180,9 +180,9 @@ extension ElementPreview { public var identifier: AnyHashable { switch self { - case .device(let device): return device.rawValue - case .fixed(let width, let height): return "(\(width), \(height))" - case .thatFits(let padding): return "thatFits (\(padding)" + case .device(let device): device.rawValue + case .fixed(let width, let height): "(\(width), \(height))" + case .thatFits(let padding): "thatFits (\(padding)" } } diff --git a/BlueprintUI/Sources/Environment/AdaptedEnvironment.swift b/BlueprintUI/Sources/Environment/AdaptedEnvironment.swift index 554249d76..af5fdbfc9 100644 --- a/BlueprintUI/Sources/Environment/AdaptedEnvironment.swift +++ b/BlueprintUI/Sources/Environment/AdaptedEnvironment.swift @@ -62,7 +62,7 @@ public struct AdaptedEnvironment: Element { ElementContent( child: wrapped, environment: { env in - for adapter in self.adapters.reversed() { + for adapter in adapters.reversed() { adapter(&env) } } diff --git a/BlueprintUI/Sources/Environment/Environment.swift b/BlueprintUI/Sources/Environment/Environment.swift index ed948eef2..490f9f65f 100644 --- a/BlueprintUI/Sources/Environment/Environment.swift +++ b/BlueprintUI/Sources/Environment/Environment.swift @@ -83,11 +83,11 @@ extension UIView { /// If no views in the superview hierarchy are managed by Blueprint, this property returns nil. var inheritedBlueprintEnvironment: Environment? { if let environment = nativeViewNodeBlueprintEnvironment { - return environment + environment } else if let superview = superview { - return superview.inheritedBlueprintEnvironment + superview.inheritedBlueprintEnvironment } else { - return nil + nil } } diff --git a/BlueprintUI/Sources/Environment/EnvironmentReader.swift b/BlueprintUI/Sources/Environment/EnvironmentReader.swift index 6222a879e..918e10489 100644 --- a/BlueprintUI/Sources/Environment/EnvironmentReader.swift +++ b/BlueprintUI/Sources/Environment/EnvironmentReader.swift @@ -25,7 +25,7 @@ public struct EnvironmentReader: Element { public var content: ElementContent { ElementContent { _, environment in - self.elementRepresentation(environment) + elementRepresentation(environment) } } diff --git a/BlueprintUI/Sources/Focus/FocusState.swift b/BlueprintUI/Sources/Focus/FocusState.swift index ff92c11f0..12367698c 100644 --- a/BlueprintUI/Sources/Focus/FocusState.swift +++ b/BlueprintUI/Sources/Focus/FocusState.swift @@ -236,7 +236,7 @@ extension FocusState { }, onBlur: { [weak self] in if let self = self, self.value == value { - self.value = self.defaultValue + self.value = defaultValue } } ) diff --git a/BlueprintUI/Sources/Internal/ElementIdentifier.swift b/BlueprintUI/Sources/Internal/ElementIdentifier.swift index 1d411b12a..7b5a4fee9 100644 --- a/BlueprintUI/Sources/Internal/ElementIdentifier.swift +++ b/BlueprintUI/Sources/Internal/ElementIdentifier.swift @@ -58,9 +58,9 @@ struct ElementIdentifier: Hashable, CustomStringConvertible { var description: String { if let key = key { - return "\(elementType).\(key).\(count)" + "\(elementType).\(key).\(count)" } else { - return "\(elementType).\(count)" + "\(elementType).\(count)" } } diff --git a/BlueprintUI/Sources/Internal/LayoutResultNode.swift b/BlueprintUI/Sources/Internal/LayoutResultNode.swift index b3cc1e936..4782144dd 100644 --- a/BlueprintUI/Sources/Internal/LayoutResultNode.swift +++ b/BlueprintUI/Sources/Internal/LayoutResultNode.swift @@ -13,13 +13,13 @@ extension Element { func layout(frame: CGRect, environment: Environment, layoutMode: LayoutMode) -> LayoutResultNode { switch layoutMode { case .legacy: - return legacyLayout( + legacyLayout( layoutAttributes: LayoutAttributes(frame: frame), environment: environment ) case .caffeinated(let options): - return caffeinatedLayout( + caffeinatedLayout( frame: frame, environment: environment, node: LayoutTreeNode( diff --git a/BlueprintUI/Sources/Layout/Column.swift b/BlueprintUI/Sources/Layout/Column.swift index a891a0480..fec1d18dc 100644 --- a/BlueprintUI/Sources/Layout/Column.swift +++ b/BlueprintUI/Sources/Layout/Column.swift @@ -34,9 +34,9 @@ public struct Column: StackElement { var stackAlignment: StackLayout.Alignment { switch self { case .fill: - return .fill + .fill case let .align(to: alignment): - return .align(to: alignment.id) + .align(to: alignment.id) } } } diff --git a/BlueprintUI/Sources/Layout/Conditionals.swift b/BlueprintUI/Sources/Layout/Conditionals.swift index b7777c45e..1a0044850 100644 --- a/BlueprintUI/Sources/Layout/Conditionals.swift +++ b/BlueprintUI/Sources/Layout/Conditionals.swift @@ -17,9 +17,9 @@ extension Element { then: (Self) -> Element ) -> Element { if isTrue { - return then(self) + then(self) } else { - return self + self } } @@ -43,9 +43,9 @@ extension Element { else: (Self) -> Element ) -> Element { if isTrue { - return then(self) + then(self) } else { - return `else`(self) + `else`(self) } } @@ -66,9 +66,9 @@ extension Element { then: (Value, Self) -> Element ) -> Element { if let value = value { - return then(value, self) + then(value, self) } else { - return self + self } } @@ -92,9 +92,9 @@ extension Element { else: (Self) -> Element ) -> Element { if let value = value { - return then(value, self) + then(value, self) } else { - return `else`(self) + `else`(self) } } diff --git a/BlueprintUI/Sources/Layout/ConstrainedSize.swift b/BlueprintUI/Sources/Layout/ConstrainedSize.swift index 6ac8d58f0..783678160 100644 --- a/BlueprintUI/Sources/Layout/ConstrainedSize.swift +++ b/BlueprintUI/Sources/Layout/ConstrainedSize.swift @@ -71,34 +71,34 @@ extension ConstrainedSize { fileprivate func applied(to value: CGFloat) -> CGFloat { switch self { case .unconstrained: - return value + value case let .atMost(max): - return min(max, value) + min(max, value) case let .atLeast(min): - return max(min, value) + max(min, value) case let .within(range): - return value.clamped(to: range) + value.clamped(to: range) case let .absolute(absoluteValue): - return absoluteValue + absoluteValue } } func applied(to constraint: SizeConstraint.Axis) -> SizeConstraint.Axis { switch constraint { case .atMost(let maxValue): - return .atMost(applied(to: maxValue)) + .atMost(applied(to: maxValue)) case .unconstrained: switch self { case .unconstrained: - return .unconstrained + .unconstrained case let .atMost(max): - return .atMost(max) + .atMost(max) case .atLeast: - return .unconstrained + .unconstrained case let .within(range): - return .atMost(range.upperBound) + .atMost(range.upperBound) case let .absolute(absoluteValue): - return .atMost(absoluteValue) + .atMost(absoluteValue) } } } @@ -143,8 +143,8 @@ extension Element { public func constrained(to sizeConstraint: SizeConstraint) -> ConstrainedSize { func toConstrainedSize(_ axis: SizeConstraint.Axis) -> ConstrainedSize.Constraint { switch axis { - case .atMost(let value): return .atMost(value) - case .unconstrained: return .unconstrained + case .atMost(let value): .atMost(value) + case .unconstrained: .unconstrained } } diff --git a/BlueprintUI/Sources/Layout/Decorate.swift b/BlueprintUI/Sources/Layout/Decorate.swift index 98c6894bf..2154f20b1 100644 --- a/BlueprintUI/Sources/Layout/Decorate.swift +++ b/BlueprintUI/Sources/Layout/Decorate.swift @@ -63,7 +63,7 @@ public struct Decorate: ProxyElement { let contentFrame = CGRect( origin: .zero, size: context.phase.onMeasure { - self.wrapped.content.measure( + wrapped.content.measure( in: context.size, environment: environment ) @@ -72,22 +72,22 @@ public struct Decorate: ProxyElement { } ) - let decorationFrame = self.position.frame( + let decorationFrame = position.frame( with: contentFrame.size, - decoration: self.decoration, + decoration: decoration, environment: environment ) layout.sizing = .fixed(contentFrame.size) - switch self.layering { + switch layering { case .above: - layout.add(with: contentFrame, child: self.wrapped) - layout.add(with: decorationFrame, child: self.decoration) + layout.add(with: contentFrame, child: wrapped) + layout.add(with: decorationFrame, child: decoration) case .below: - layout.add(with: decorationFrame, child: self.decoration) - layout.add(with: contentFrame, child: self.wrapped) + layout.add(with: decorationFrame, child: decoration) + layout.add(with: contentFrame, child: wrapped) } } } @@ -116,10 +116,10 @@ extension Decorate { var alignment: Alignment { switch self { - case .topLeft: return .topLeading - case .topRight: return .topTrailing - case .bottomLeft: return .bottomLeading - case .bottomRight: return .bottomTrailing + case .topLeft: .topLeading + case .topRight: .topTrailing + case .bottomLeft: .bottomLeading + case .bottomRight: .bottomTrailing } } } diff --git a/BlueprintUI/Sources/Layout/GeometryReader.swift b/BlueprintUI/Sources/Layout/GeometryReader.swift index 72207ae40..ea58abc48 100644 --- a/BlueprintUI/Sources/Layout/GeometryReader.swift +++ b/BlueprintUI/Sources/Layout/GeometryReader.swift @@ -32,7 +32,7 @@ public struct GeometryReader: Element { public var content: ElementContent { ElementContent { constraint, environment -> Element in - self.elementRepresentation(GeometryProxy(environment: environment, constraint: constraint)) + elementRepresentation(GeometryProxy(environment: environment, constraint: constraint)) } } diff --git a/BlueprintUI/Sources/Layout/GridRow.swift b/BlueprintUI/Sources/Layout/GridRow.swift index e2d4b4a0f..57179a8ee 100644 --- a/BlueprintUI/Sources/Layout/GridRow.swift +++ b/BlueprintUI/Sources/Layout/GridRow.swift @@ -327,13 +327,13 @@ extension GridRow { private func _yVector(rowHeight: CGFloat) -> (CGFloat) -> (origin: CGFloat, height: CGFloat) { switch verticalAlignment { case .fill: - return { _ in (0, rowHeight) } + { _ in (0, rowHeight) } case .align(let id) where id == .top: - return { height in (0, height) } + { height in (0, height) } case .align(let id) where id == .center: - return { height in ((rowHeight - height) / 2.0, height) } + { height in ((rowHeight - height) / 2.0, height) } case .align(let id) where id == .bottom: - return { height in (rowHeight - height, height) } + { height in (rowHeight - height, height) } case .align: fatalError("GridRow supports fill, top, center, and bottom alignment.") } diff --git a/BlueprintUI/Sources/Layout/Layout.swift b/BlueprintUI/Sources/Layout/Layout.swift index 1217af798..0da32b934 100644 --- a/BlueprintUI/Sources/Layout/Layout.swift +++ b/BlueprintUI/Sources/Layout/Layout.swift @@ -136,7 +136,7 @@ public protocol LegacyLayout { extension LegacyLayout where Traits == () { public static var defaultTraits: () { - return () + () } } diff --git a/BlueprintUI/Sources/Layout/LayoutMode.swift b/BlueprintUI/Sources/Layout/LayoutMode.swift index 616782637..deb10d4ae 100644 --- a/BlueprintUI/Sources/Layout/LayoutMode.swift +++ b/BlueprintUI/Sources/Layout/LayoutMode.swift @@ -36,9 +36,9 @@ public enum LayoutMode: Equatable { public var name: String { switch self { case .legacy: - return "Legacy" + "Legacy" case .caffeinated: - return "Caffeinated" + "Caffeinated" } } } @@ -47,17 +47,17 @@ extension LayoutMode: CustomStringConvertible { public var description: String { switch self { case .legacy: - return "Legacy" + "Legacy" case .caffeinated(let options): switch (options.hintRangeBoundaries, options.searchUnconstrainedKeys) { case (true, true): - return "Caffeinated (hint+search)" + "Caffeinated (hint+search)" case (true, false): - return "Caffeinated (hint)" + "Caffeinated (hint)" case (false, true): - return "Caffeinated (search)" + "Caffeinated (search)" case (false, false): - return "Caffeinated" + "Caffeinated" } } } diff --git a/BlueprintUI/Sources/Layout/LayoutWriter.swift b/BlueprintUI/Sources/Layout/LayoutWriter.swift index 317cef961..1019a39f1 100644 --- a/BlueprintUI/Sources/Layout/LayoutWriter.swift +++ b/BlueprintUI/Sources/Layout/LayoutWriter.swift @@ -44,14 +44,14 @@ public struct LayoutWriter: Element { func layoutPhase() -> Context.LayoutPhase { switch phase { - case .measurement: return .measurement - case .layout: return .layout(size.maximum) + case .measurement: .measurement + case .layout: .layout(size.maximum) } } var builder = Builder() - self.build( + build( Context( size: size, phase: layoutPhase() @@ -167,7 +167,7 @@ extension LayoutWriter { func measure(with builder: Builder) -> CGSize { switch self { case .unionOfChildren: - return CGSize( + CGSize( width: builder.children.reduce(0.0) { width, child in max(width, child.frame.maxX) }, @@ -176,7 +176,7 @@ extension LayoutWriter { } ) case .fixed(let size): - return size + size } } } @@ -224,8 +224,8 @@ extension LayoutWriter.Context { onLayout: (CGSize) -> Value ) -> Value { switch self { - case .measurement: return onMeasure() - case .layout(let size): return onLayout(size) + case .measurement: onMeasure() + case .layout(let size): onLayout(size) } } } diff --git a/BlueprintUI/Sources/Layout/Row.swift b/BlueprintUI/Sources/Layout/Row.swift index 6999a1dd0..e6874b4e2 100644 --- a/BlueprintUI/Sources/Layout/Row.swift +++ b/BlueprintUI/Sources/Layout/Row.swift @@ -42,9 +42,9 @@ public struct Row: StackElement { var stackAlignment: StackLayout.Alignment { switch self { case .fill: - return .fill + .fill case let .align(to: alignment): - return .align(to: alignment.id) + .align(to: alignment.id) } } } diff --git a/BlueprintUI/Sources/Layout/Stack.swift b/BlueprintUI/Sources/Layout/Stack.swift index bee61dd2b..a2064d408 100644 --- a/BlueprintUI/Sources/Layout/Stack.swift +++ b/BlueprintUI/Sources/Layout/Stack.swift @@ -503,9 +503,9 @@ extension StackLayout { let flexibleConstraint: SizeConstraint = { switch axis { case .horizontal: - return .init(width: flexibleMagnitude, height: constraint.height) + .init(width: flexibleMagnitude, height: constraint.height) case .vertical: - return .init(width: constraint.width, height: flexibleMagnitude) + .init(width: constraint.width, height: flexibleMagnitude) } }() @@ -959,18 +959,18 @@ extension StackLayout { func size(axis: StackLayout.Axis) -> CGSize { switch axis { case .horizontal: - return CGSize(width: self.axis, height: cross) + CGSize(width: self.axis, height: cross) case .vertical: - return CGSize(width: cross, height: self.axis) + CGSize(width: cross, height: self.axis) } } func point(axis: StackLayout.Axis) -> CGPoint { switch axis { case .horizontal: - return CGPoint(x: self.axis, y: cross) + CGPoint(x: self.axis, y: cross) case .vertical: - return CGPoint(x: cross, y: self.axis) + CGPoint(x: cross, y: self.axis) } } } @@ -985,9 +985,9 @@ extension StackLayout { var sizeConstraint: SizeConstraint.Axis { switch self { case .exactly(let max), .atMost(let max): - return .atMost(max) + .atMost(max) case .unconstrained: - return .unconstrained + .unconstrained } } } @@ -998,9 +998,9 @@ extension StackLayout { func constraint(axis layoutAxis: StackLayout.Axis) -> SizeConstraint { switch layoutAxis { case .horizontal: - return SizeConstraint(width: axis.sizeConstraint, height: cross.sizeConstraint) + SizeConstraint(width: axis.sizeConstraint, height: cross.sizeConstraint) case .vertical: - return SizeConstraint(width: cross.sizeConstraint, height: axis.sizeConstraint) + SizeConstraint(width: cross.sizeConstraint, height: axis.sizeConstraint) } } } @@ -1044,21 +1044,21 @@ extension CGSize { fileprivate func stackVector(axis: StackLayout.Axis) -> StackLayout.Vector { switch axis { case .horizontal: - return StackLayout.Vector(axis: width, cross: height) + StackLayout.Vector(axis: width, cross: height) case .vertical: - return StackLayout.Vector(axis: height, cross: width) + StackLayout.Vector(axis: height, cross: width) } } fileprivate func vectorConstraint(axis: StackLayout.Axis) -> StackLayout.VectorConstraint { switch axis { case .horizontal: - return StackLayout.VectorConstraint( + StackLayout.VectorConstraint( axis: .exactly(width), cross: .exactly(height) ) case .vertical: - return StackLayout.VectorConstraint( + StackLayout.VectorConstraint( axis: .exactly(height), cross: .exactly(width) ) @@ -1068,18 +1068,18 @@ extension CGSize { fileprivate func axis(on axis: StackLayout.Axis) -> CGFloat { switch axis { case .horizontal: - return width + width case .vertical: - return height + height } } fileprivate func cross(on axis: StackLayout.Axis) -> CGFloat { switch axis { case .horizontal: - return height + height case .vertical: - return width + width } } } @@ -1088,27 +1088,27 @@ extension SizeConstraint { fileprivate func vectorConstraint(on axis: StackLayout.Axis) -> StackLayout.VectorConstraint { switch axis { case .horizontal: - return StackLayout.VectorConstraint(axis: width.vectorConstraint, cross: height.vectorConstraint) + StackLayout.VectorConstraint(axis: width.vectorConstraint, cross: height.vectorConstraint) case .vertical: - return StackLayout.VectorConstraint(axis: height.vectorConstraint, cross: width.vectorConstraint) + StackLayout.VectorConstraint(axis: height.vectorConstraint, cross: width.vectorConstraint) } } fileprivate func axis(on axis: StackLayout.Axis) -> SizeConstraint.Axis { switch axis { case .horizontal: - return width + width case .vertical: - return height + height } } fileprivate func cross(on axis: StackLayout.Axis) -> SizeConstraint.Axis { switch axis { case .horizontal: - return height + height case .vertical: - return width + width } } } @@ -1117,9 +1117,9 @@ extension SizeConstraint.Axis { fileprivate var vectorConstraint: StackLayout.VectorConstraint.Axis { switch self { case .atMost(let max): - return .atMost(max) + .atMost(max) case .unconstrained: - return .unconstrained + .unconstrained } } } @@ -1157,19 +1157,19 @@ extension StackLayout { fileprivate var growPriority: CGFloat { switch self { - case .fixed: return 0 - case .flexible: return 1 - case .grows: return 1 - case .shrinks: return 0 + case .fixed: 0 + case .flexible: 1 + case .grows: 1 + case .shrinks: 0 } } fileprivate var shrinkPriority: CGFloat { switch self { - case .fixed: return 0 - case .flexible: return 1 - case .grows: return 0 - case .shrinks: return 1 + case .fixed: 0 + case .flexible: 1 + case .grows: 0 + case .shrinks: 1 } } } diff --git a/BlueprintUI/Sources/Measuring/SizeConstraint.swift b/BlueprintUI/Sources/Measuring/SizeConstraint.swift index ab52a210b..3f5642ee1 100644 --- a/BlueprintUI/Sources/Measuring/SizeConstraint.swift +++ b/BlueprintUI/Sources/Measuring/SizeConstraint.swift @@ -90,9 +90,9 @@ extension SizeConstraint { public var maximum: CGFloat { switch self { case .atMost(let value): - return value + value case .unconstrained: - return Axis.maxValue + Axis.maxValue } } @@ -100,9 +100,9 @@ extension SizeConstraint { public var minimum: CGFloat { switch self { case .atMost(_): - return 0.0 + 0.0 case .unconstrained: - return 0.0 + 0.0 } } @@ -110,19 +110,19 @@ extension SizeConstraint { public var constrainedValue: CGFloat? { switch self { case .atMost(let value): - return value + value case .unconstrained: - return nil + nil } } func map(transform: (CGFloat) -> (CGFloat)) -> Self { switch self { case .atMost(let value): - return .atMost(transform(value)) + .atMost(transform(value)) case .unconstrained: - return .unconstrained + .unconstrained } } @@ -133,9 +133,9 @@ extension SizeConstraint { public static func + (lhs: SizeConstraint.Axis, rhs: CGFloat) -> SizeConstraint.Axis { switch lhs { case .atMost(let limit): - return .atMost(limit + rhs) + .atMost(limit + rhs) case .unconstrained: - return .unconstrained + .unconstrained } } @@ -144,9 +144,9 @@ extension SizeConstraint { public static func - (lhs: SizeConstraint.Axis, rhs: CGFloat) -> SizeConstraint.Axis { switch lhs { case .atMost(let limit): - return .atMost(limit - rhs) + .atMost(limit - rhs) case .unconstrained: - return .unconstrained + .unconstrained } } @@ -155,9 +155,9 @@ extension SizeConstraint { public static func / (lhs: SizeConstraint.Axis, rhs: CGFloat) -> SizeConstraint.Axis { switch lhs { case .atMost(let limit): - return .atMost(limit / rhs) + .atMost(limit / rhs) case .unconstrained: - return .unconstrained + .unconstrained } } @@ -166,9 +166,9 @@ extension SizeConstraint { public static func * (lhs: SizeConstraint.Axis, rhs: CGFloat) -> SizeConstraint.Axis { switch lhs { case .atMost(let limit): - return .atMost(limit * rhs) + .atMost(limit * rhs) case .unconstrained: - return .unconstrained + .unconstrained } } @@ -176,9 +176,9 @@ extension SizeConstraint { public var isGreaterThanZero: Bool { switch self { case .atMost(let limit): - return limit > 0 + limit > 0 case .unconstrained: - return true + true } } @@ -211,9 +211,9 @@ extension SizeConstraint { public var description: String { switch self { case .atMost(let max): - return "atMost(\(max))" + "atMost(\(max))" case .unconstrained: - return "unconstrained" + "unconstrained" } } } @@ -238,12 +238,12 @@ extension SizeConstraint { switch axis { case .atMost(let maxAxis): if maxAxis.isInfinite || maxAxis == .greatestFiniteMagnitude { - return .unconstrained + .unconstrained } else { - return axis + axis } case .unconstrained: - return axis + axis } } } diff --git a/BlueprintUI/Sources/ViewDescription/ViewDescription.swift b/BlueprintUI/Sources/ViewDescription/ViewDescription.swift index 2d68b1968..30f586568 100644 --- a/BlueprintUI/Sources/ViewDescription/ViewDescription.swift +++ b/BlueprintUI/Sources/ViewDescription/ViewDescription.swift @@ -235,9 +235,9 @@ extension ViewDescription.Configuration { public subscript(keyPath: ReferenceWritableKeyPath) -> Value? { get { if let binding = bindings[keyPath] as? ValueBinding { - return binding.value + binding.value } else { - return nil + nil } } set { @@ -263,9 +263,9 @@ extension ViewDescription.Configuration { public subscript(keyPath: ReferenceWritableKeyPath) -> Value? { get { if let binding = bindings[keyPath] as? ValueBinding { - return binding.value + binding.value } else { - return nil + nil } } set { diff --git a/BlueprintUI/Tests/BlueprintViewTests.swift b/BlueprintUI/Tests/BlueprintViewTests.swift index c36af8583..7f478348f 100755 --- a/BlueprintUI/Tests/BlueprintViewTests.swift +++ b/BlueprintUI/Tests/BlueprintViewTests.swift @@ -377,9 +377,9 @@ class BlueprintViewTests: XCTestCase { var content: ElementContent { if let child = child { - return .init(child: child) + .init(child: child) } else { - return .init(intrinsicSize: .zero) + .init(intrinsicSize: .zero) } } @@ -878,9 +878,9 @@ private struct LifecycleTestElement: Element { var content: ElementContent { if let wrapped = wrapped { - return ElementContent(child: wrapped) + ElementContent(child: wrapped) } else { - return ElementContent(intrinsicSize: .zero) + ElementContent(intrinsicSize: .zero) } } @@ -899,9 +899,9 @@ private enum LifecycleTestEvent: Equatable, CustomStringConvertible { var description: String { switch self { case .appear(let i): - return "appear(\(i))" + "appear(\(i))" case .disappear(let i): - return "disappear(\(i))" + "disappear(\(i))" } } } diff --git a/BlueprintUI/Tests/EnvironmentTests.swift b/BlueprintUI/Tests/EnvironmentTests.swift index a1ad794c9..186c510a9 100644 --- a/BlueprintUI/Tests/EnvironmentTests.swift +++ b/BlueprintUI/Tests/EnvironmentTests.swift @@ -294,7 +294,7 @@ private struct TestElement: Element { func backingViewDescription(with context: ViewDescriptionContext) -> ViewDescription? { TestView.describe { config in - config[\.testValue] = self.value + config[\.testValue] = value } } } @@ -323,11 +323,11 @@ private enum TestValue { var size: CGSize { switch self { case .defaultValue: - return CGSize(width: 2, height: 3) + CGSize(width: 2, height: 3) case .right: - return CGSize(width: 4, height: 5) + CGSize(width: 4, height: 5) case .wrong: - return CGSize(width: 6, height: 7) + CGSize(width: 6, height: 7) } } diff --git a/BlueprintUI/Tests/GeometryReaderTests.swift b/BlueprintUI/Tests/GeometryReaderTests.swift index 043c15665..896de2f0c 100644 --- a/BlueprintUI/Tests/GeometryReaderTests.swift +++ b/BlueprintUI/Tests/GeometryReaderTests.swift @@ -147,9 +147,9 @@ extension SizeConstraint.Axis { fileprivate var isConstrained: Bool { switch self { case .atMost: - return true + true case .unconstrained: - return false + false } } } diff --git a/BlueprintUI/Tests/PixelBoundaryTests.swift b/BlueprintUI/Tests/PixelBoundaryTests.swift index 6883503be..cc9f24d5a 100644 --- a/BlueprintUI/Tests/PixelBoundaryTests.swift +++ b/BlueprintUI/Tests/PixelBoundaryTests.swift @@ -193,9 +193,9 @@ class PixelBoundaryTests: XCTestCase { var content: ElementContent { if let wrappedElement = wrappedElement { - return ElementContent(child: wrappedElement) + ElementContent(child: wrappedElement) } else { - return ElementContent(intrinsicSize: .zero) + ElementContent(intrinsicSize: .zero) } } diff --git a/BlueprintUI/Tests/StackTests.swift b/BlueprintUI/Tests/StackTests.swift index 9e212fa9d..d91bc0d0b 100644 --- a/BlueprintUI/Tests/StackTests.swift +++ b/BlueprintUI/Tests/StackTests.swift @@ -1054,9 +1054,9 @@ class StackTests: XCTestCase { func element(on axis: StackLayout.Axis) -> Element { switch self { case .fixed: - return Spacer(size: CGSize(width: 10, height: 10)) + Spacer(size: CGSize(width: 10, height: 10)) case .flex: - return WrappingElement(axis: axis) + WrappingElement(axis: axis) } } } @@ -1357,21 +1357,21 @@ class StackTests: XCTestCase { var content: ElementContent { ElementContent { constraint -> CGSize in - switch self.axis { + switch axis { case .horizontal: - let itemsPerLine = max(1, Int(constraint.width.maximum / self.itemSize.width)) - let lineCount = (self.itemCount + itemsPerLine - 1) / itemsPerLine + let itemsPerLine = max(1, Int(constraint.width.maximum / itemSize.width)) + let lineCount = (itemCount + itemsPerLine - 1) / itemsPerLine return CGSize( - width: CGFloat(itemsPerLine) * self.itemSize.width, - height: CGFloat(lineCount) * self.itemSize.height + width: CGFloat(itemsPerLine) * itemSize.width, + height: CGFloat(lineCount) * itemSize.height ) case .vertical: - let itemsPerColumn = max(1, Int(constraint.height.maximum / self.itemSize.height)) - let columnCount = (self.itemCount + itemsPerColumn - 1) / itemsPerColumn + let itemsPerColumn = max(1, Int(constraint.height.maximum / itemSize.height)) + let columnCount = (itemCount + itemsPerColumn - 1) / itemsPerColumn let size = CGSize( - width: CGFloat(columnCount) * self.itemSize.width, - height: CGFloat(itemsPerColumn) * self.itemSize.height + width: CGFloat(columnCount) * itemSize.width, + height: CGFloat(itemsPerColumn) * itemSize.height ) return size } diff --git a/BlueprintUICommonControls/Sources/AccessibilityElement.swift b/BlueprintUICommonControls/Sources/AccessibilityElement.swift index 014cec888..74eb33de4 100644 --- a/BlueprintUICommonControls/Sources/AccessibilityElement.swift +++ b/BlueprintUICommonControls/Sources/AccessibilityElement.swift @@ -261,23 +261,23 @@ extension AccessibilityElement.Trait: Hashable, Equatable { /// - Important: ⚠️ This implementation does not take equality of associated values on `.adjustable` into account. ⚠️ private var internalValue: Int { switch self { - case .button: return 0 - case .link: return 1 - case .header: return 2 - case .searchField: return 3 - case .image: return 4 - case .selected: return 5 - case .playsSound: return 6 - case .keyboardKey: return 7 - case .staticText: return 8 - case .summaryElement: return 9 - case .notEnabled: return 10 - case .updatesFrequently: return 11 - case .startsMediaSession: return 12 - case .adjustable: return 13 - case .allowsDirectInteraction: return 14 - case .causesPageTurn: return 15 - case .tabBar: return 16 + case .button: 0 + case .link: 1 + case .header: 2 + case .searchField: 3 + case .image: 4 + case .selected: 5 + case .playsSound: 6 + case .keyboardKey: 7 + case .staticText: 8 + case .summaryElement: 9 + case .notEnabled: 10 + case .updatesFrequently: 11 + case .startsMediaSession: 12 + case .adjustable: 13 + case .allowsDirectInteraction: 14 + case .causesPageTurn: 15 + case .tabBar: 16 } } diff --git a/BlueprintUICommonControls/Sources/AttributedLabel+Environment.swift b/BlueprintUICommonControls/Sources/AttributedLabel+Environment.swift index ac81cb1f9..8a900a3f0 100644 --- a/BlueprintUICommonControls/Sources/AttributedLabel+Environment.swift +++ b/BlueprintUICommonControls/Sources/AttributedLabel+Environment.swift @@ -25,11 +25,11 @@ public struct URLHandlerEnvironmentKey: EnvironmentKey { public static let defaultValue: URLHandler = { // This is our best guess for "is this executable an extension?" if let _ = Bundle.main.infoDictionary?["NSExtension"] { - return NullURLHandler() + NullURLHandler() } else if Bundle.main.bundlePath.hasSuffix(".appex") { - return NullURLHandler() + NullURLHandler() } else { - return DefaultURLHandler() + DefaultURLHandler() } }() } diff --git a/BlueprintUICommonControls/Sources/AttributedLabel.swift b/BlueprintUICommonControls/Sources/AttributedLabel.swift index a35dc24ae..80cccd93d 100644 --- a/BlueprintUICommonControls/Sources/AttributedLabel.swift +++ b/BlueprintUICommonControls/Sources/AttributedLabel.swift @@ -116,9 +116,9 @@ public struct AttributedLabel: Element, Hashable { /// The text to pass to the underlying `UILabel`, normalized for display if necessary. var displayableAttributedText: NSAttributedString { if needsTextNormalization || linkDetectionTypes.isEmpty == false { - return attributedText.normalizingForView(with: numberOfLines) + attributedText.normalizingForView(with: numberOfLines) } else { - return attributedText + attributedText } } @@ -176,10 +176,10 @@ extension AttributedLabel { var checkingType: NSTextCheckingResult.CheckingType { switch self { - case .date: return .date - case .address: return .address - case .link: return .link - case .phoneNumber: return .phoneNumber + case .date: .date + case .address: .address + case .link: .link + case .phoneNumber: .phoneNumber } } } @@ -228,14 +228,14 @@ extension AttributedLabel { return nil } - self.accessibilityLinkIndex += predicate.searchDirection == .next ? 1 : -1 - self.accessibilityLinkIndex = min( - self.accessibilityLinks.count - 1, - self.accessibilityLinkIndex + accessibilityLinkIndex += predicate.searchDirection == .next ? 1 : -1 + accessibilityLinkIndex = min( + accessibilityLinks.count - 1, + accessibilityLinkIndex ) - self.accessibilityLinkIndex = max(0, self.accessibilityLinkIndex) + accessibilityLinkIndex = max(0, accessibilityLinkIndex) - let link = self.accessibilityLinks[self.accessibilityLinkIndex] + let link = accessibilityLinks[accessibilityLinkIndex] return UIAccessibilityCustomRotorItemResult(targetElement: link, targetRange: nil) }, ] diff --git a/BlueprintUICommonControls/Sources/Box.swift b/BlueprintUICommonControls/Sources/Box.swift index 804c64b0c..c349f0254 100644 --- a/BlueprintUICommonControls/Sources/Box.swift +++ b/BlueprintUICommonControls/Sources/Box.swift @@ -47,9 +47,9 @@ public struct Box: Element { public var content: ElementContent { if let wrappedElement = wrappedElement { - return ElementContent(child: wrappedElement) + ElementContent(child: wrappedElement) } else { - return ElementContent(intrinsicSize: .zero) + ElementContent(intrinsicSize: .zero) } } @@ -58,63 +58,63 @@ public struct Box: Element { config.apply { view in - if self.backgroundColor != view.backgroundColor { - view.backgroundColor = self.backgroundColor + if backgroundColor != view.backgroundColor { + view.backgroundColor = backgroundColor } - if self.cornerStyle.cornerMask != view.layer.maskedCorners { - view.layer.maskedCorners = self.cornerStyle.cornerMask + if cornerStyle.cornerMask != view.layer.maskedCorners { + view.layer.maskedCorners = cornerStyle.cornerMask } - if self.cornerStyle.radius(for: context.bounds) != view.layer.cornerRadius { - view.layer.cornerRadius = self.cornerStyle.radius(for: context.bounds) + if cornerStyle.radius(for: context.bounds) != view.layer.cornerRadius { + view.layer.cornerRadius = cornerStyle.radius(for: context.bounds) } - if self.cornerCurve.toLayerCornerCurve != view.layer.cornerCurve { - view.layer.cornerCurve = self.cornerCurve.toLayerCornerCurve + if cornerCurve.toLayerCornerCurve != view.layer.cornerCurve { + view.layer.cornerCurve = cornerCurve.toLayerCornerCurve } - if self.borderStyle.color?.cgColor != view.layer.borderColor { - view.layer.borderColor = self.borderStyle.color?.cgColor + if borderStyle.color?.cgColor != view.layer.borderColor { + view.layer.borderColor = borderStyle.color?.cgColor } - if self.borderStyle.width != view.layer.borderWidth { - view.layer.borderWidth = self.borderStyle.width + if borderStyle.width != view.layer.borderWidth { + view.layer.borderWidth = borderStyle.width } - if self.cornerStyle.shadowRoundedCorners != view.shadowRoundCorners { - view.shadowRoundCorners = self.cornerStyle.shadowRoundedCorners + if cornerStyle.shadowRoundedCorners != view.shadowRoundCorners { + view.shadowRoundCorners = cornerStyle.shadowRoundedCorners } - if self.shadowStyle.radius != view.layer.shadowRadius { - view.layer.shadowRadius = self.shadowStyle.radius + if shadowStyle.radius != view.layer.shadowRadius { + view.layer.shadowRadius = shadowStyle.radius } - if self.shadowStyle.offset != view.layer.shadowOffset { - view.layer.shadowOffset = self.shadowStyle.offset + if shadowStyle.offset != view.layer.shadowOffset { + view.layer.shadowOffset = shadowStyle.offset } - if self.shadowStyle.color?.cgColor != view.layer.shadowColor { - view.layer.shadowColor = self.shadowStyle.color?.cgColor + if shadowStyle.color?.cgColor != view.layer.shadowColor { + view.layer.shadowColor = shadowStyle.color?.cgColor } - if self.shadowStyle.opacity != CGFloat(view.layer.shadowOpacity) { - view.layer.shadowOpacity = Float(self.shadowStyle.opacity) + if shadowStyle.opacity != CGFloat(view.layer.shadowOpacity) { + view.layer.shadowOpacity = Float(shadowStyle.opacity) } /// `.contentView` is used for clipping, make sure the corner radius /// matches. - if self.clipsContent != view.contentView.clipsToBounds { - view.contentView.clipsToBounds = self.clipsContent + if clipsContent != view.contentView.clipsToBounds { + view.contentView.clipsToBounds = clipsContent } - if self.cornerStyle.radius(for: context.bounds) != view.contentView.layer.cornerRadius { - view.contentView.layer.cornerRadius = self.cornerStyle.radius(for: context.bounds) + if cornerStyle.radius(for: context.bounds) != view.contentView.layer.cornerRadius { + view.contentView.layer.cornerRadius = cornerStyle.radius(for: context.bounds) } - if self.cornerStyle.cornerMask != view.contentView.layer.maskedCorners { - view.contentView.layer.maskedCorners = self.cornerStyle.cornerMask + if cornerStyle.cornerMask != view.contentView.layer.maskedCorners { + view.contentView.layer.maskedCorners = cornerStyle.cornerMask } } @@ -146,8 +146,8 @@ extension Box { @available(iOS 13.0, *) var toLayerCornerCurve: CALayerCornerCurve { switch self { - case .circular: return .circular - case .continuous: return .continuous + case .circular: .circular + case .continuous: .continuous } } } @@ -203,18 +203,18 @@ extension Box.CornerStyle { fileprivate var cornerMask: CACornerMask { switch self { case .square, .capsule: - return Corners.all.toCACornerMask + Corners.all.toCACornerMask case let .rounded(_, corners): - return corners.toCACornerMask + corners.toCACornerMask } } fileprivate var shadowRoundedCorners: UIRectCorner { switch self { case .square, .capsule: - return Corners.all.toUIRectCorner + Corners.all.toUIRectCorner case let .rounded(_, corners): - return corners.toUIRectCorner + corners.toUIRectCorner } } } @@ -224,18 +224,18 @@ extension Box.BorderStyle { fileprivate var width: CGFloat { switch self { case .none: - return 0.0 + 0.0 case let .solid(_, width): - return width + width } } fileprivate var color: UIColor? { switch self { case .none: - return nil + nil case let .solid(color, _): - return color + color } } @@ -246,36 +246,36 @@ extension Box.ShadowStyle { fileprivate var radius: CGFloat { switch self { case .none: - return 0.0 + 0.0 case let .simple(radius, _, _, _): - return radius + radius } } fileprivate var opacity: CGFloat { switch self { case .none: - return 0.0 + 0.0 case let .simple(_, opacity, _, _): - return opacity + opacity } } fileprivate var offset: CGSize { switch self { case .none: - return .zero + .zero case let .simple(_, _, offset, _): - return offset + offset } } fileprivate var color: UIColor? { switch self { case .none: - return nil + nil case let .simple(_, _, _, color): - return color + color } } diff --git a/BlueprintUICommonControls/Sources/EditingMenu.swift b/BlueprintUICommonControls/Sources/EditingMenu.swift index 431f3c3d2..ea333969c 100644 --- a/BlueprintUICommonControls/Sources/EditingMenu.swift +++ b/BlueprintUICommonControls/Sources/EditingMenu.swift @@ -259,42 +259,42 @@ extension EditingMenuItem { var selector: Selector { switch self { case .system(let kind, _): - return kind.selector + kind.selector case .custom(_, let selector, _): - return selector + selector } } var onSelect: OnSelect { switch self { case .system(_, let onSelect): - return onSelect + onSelect case .custom(_, _, let onSelect): - return onSelect + onSelect } } var isCustom: Bool { switch self { - case .system: return false - case .custom: return true + case .system: false + case .custom: true } } var isSystem: Bool { switch self { - case .system: return true - case .custom: return false + case .system: true + case .custom: false } } var asMenuItem: UIMenuItem? { switch self { case .system: - return nil + nil case .custom(let title, let selector, _): - return UIMenuItem(title: title, action: selector) + UIMenuItem(title: title, action: selector) } } } @@ -577,8 +577,8 @@ extension EditingMenu { private func perform(kind kindToPerform: EditingMenuItem.Kind.System) { let action = items.first { item in switch item { - case .system(let kind, _): return kind == kindToPerform - case .custom: return false + case .system(let kind, _): kind == kindToPerform + case .custom: false } } diff --git a/BlueprintUICommonControls/Sources/Image.swift b/BlueprintUICommonControls/Sources/Image.swift index dd9c56e5f..54c2aad8b 100644 --- a/BlueprintUICommonControls/Sources/Image.swift +++ b/BlueprintUICommonControls/Sources/Image.swift @@ -83,10 +83,10 @@ extension Image { fileprivate var uiViewContentMode: UIView.ContentMode { switch self { - case .center: return .center - case .stretch: return .scaleToFill - case .aspectFit: return .scaleAspectFit - case .aspectFill: return .scaleAspectFill + case .center: .center + case .stretch: .scaleToFill + case .aspectFit: .scaleAspectFit + case .aspectFill: .scaleAspectFill } } } @@ -98,9 +98,9 @@ extension CGSize { fileprivate var aspectRatio: CGFloat { if height > 0.0 { - return width / height + width / height } else { - return 0.0 + 0.0 } } diff --git a/BlueprintUICommonControls/Sources/Internal/KeyboardObserver.swift b/BlueprintUICommonControls/Sources/Internal/KeyboardObserver.swift index 3fa500ddf..37649fbc1 100644 --- a/BlueprintUICommonControls/Sources/Internal/KeyboardObserver.swift +++ b/BlueprintUICommonControls/Sources/Internal/KeyboardObserver.swift @@ -264,11 +264,11 @@ extension KeyboardObserver { private static let isExtensionContext: Bool = { // This is our best guess for "is this executable an extension?" if let _ = Bundle.main.infoDictionary?["NSExtension"] { - return true + true } else if Bundle.main.bundlePath.hasSuffix(".appex") { - return true + true } else { - return false + false } }() diff --git a/BlueprintUICommonControls/Sources/Rule.swift b/BlueprintUICommonControls/Sources/Rule.swift index 5495b3279..19ff038fc 100644 --- a/BlueprintUICommonControls/Sources/Rule.swift +++ b/BlueprintUICommonControls/Sources/Rule.swift @@ -23,9 +23,9 @@ public struct Rule: ProxyElement { var value: CGFloat { switch self { case .hairline: - return 1.0 / UIScreen.main.scale + 1.0 / UIScreen.main.scale case .points(let points): - return points + points } } } @@ -61,18 +61,18 @@ public struct Rule: ProxyElement { private var width: ConstrainedSize.Constraint { switch orientation { case .horizontal: - return .unconstrained + .unconstrained case .vertical: - return .absolute(thickness.value) + .absolute(thickness.value) } } private var height: ConstrainedSize.Constraint { switch orientation { case .horizontal: - return .absolute(thickness.value) + .absolute(thickness.value) case .vertical: - return .unconstrained + .unconstrained } } } diff --git a/BlueprintUICommonControls/Sources/ScrollView.swift b/BlueprintUICommonControls/Sources/ScrollView.swift index 12ee1a0bd..78d1ca922 100644 --- a/BlueprintUICommonControls/Sources/ScrollView.swift +++ b/BlueprintUICommonControls/Sources/ScrollView.swift @@ -99,20 +99,20 @@ extension ScrollView { func fittedSize(in constraint: SizeConstraint, child: Measurable) -> CGSize { switch contentSize { case .custom(let size): - return size + size case .fittingContent: - return child.measure(in: .unconstrained) + child.measure(in: .unconstrained) case .fittingHeight: - return child.measure( + child.measure( in: SizeConstraint( width: constraint.width, height: .unconstrained )) case .fittingWidth: - return child.measure( + child.measure( in: SizeConstraint( width: .unconstrained, height: constraint.height @@ -167,13 +167,13 @@ extension ScrollView { func fittedSize(in proposal: SizeConstraint, subelement: Subelement) -> CGSize { switch contentSize { case .custom(let size): - return size + size case .fittingContent: - return subelement.sizeThatFits(.unconstrained) + subelement.sizeThatFits(.unconstrained) case .fittingHeight: - return subelement.sizeThatFits( + subelement.sizeThatFits( SizeConstraint( width: proposal.width, height: .unconstrained @@ -181,7 +181,7 @@ extension ScrollView { ) case .fittingWidth: - return subelement.sizeThatFits( + subelement.sizeThatFits( SizeConstraint( width: .unconstrained, height: proposal.height @@ -282,18 +282,18 @@ extension ScrollView { var needsRefreshControl: Bool { switch self { case .disabled: - return false + false case .enabled, .refreshing: - return true + true } } var isRefreshing: Bool { switch self { case .refreshing: - return true + true case .disabled, .enabled: - return false + false } } @@ -326,11 +326,11 @@ fileprivate final class ScrollerWrapperView: UIView { guard let self = self else { return } let context = ScrollView.ContentOffset.ScrollingContext( - contentSize: self.scrollView.contentSize, - scrollViewBounds: self.scrollView.bounds, - contentInsets: self.scrollView.contentInset + contentSize: scrollView.contentSize, + scrollViewBounds: scrollView.bounds, + contentInsets: scrollView.contentInset ) - self.scrollView.setContentOffset(offset.provider(context), animated: animated) + scrollView.setContentOffset(offset.provider(context), animated: animated) } } } diff --git a/BlueprintUICommonControls/Sources/SegmentedControl.swift b/BlueprintUICommonControls/Sources/SegmentedControl.swift index 23f46ac84..dac1683fb 100644 --- a/BlueprintUICommonControls/Sources/SegmentedControl.swift +++ b/BlueprintUICommonControls/Sources/SegmentedControl.swift @@ -66,9 +66,9 @@ extension SegmentedControl { fileprivate var resolvedIndex: Int { switch self { case .none: - return UISegmentedControl.noSegment + UISegmentedControl.noSegment case let .index(index): - return index + index } } } @@ -101,9 +101,9 @@ extension SegmentedControl.Item { fileprivate var resolvedWidth: CGFloat { switch self { case .automatic: - return 0.0 + 0.0 case let .specific(width): - return width + width } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 61564a628..35d8afc62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Internal +- Local development environment switched from CocoaPods to Tuist. + ## [5.1.0] - 2024-11-25 ### Added diff --git a/Package.resolved b/Package.resolved deleted file mode 100644 index 06074d862..000000000 --- a/Package.resolved +++ /dev/null @@ -1,14 +0,0 @@ -{ - "pins" : [ - { - "identity" : "swiftformat", - "kind" : "remoteSourceControl", - "location" : "https://github.com/nicklockwood/SwiftFormat", - "state" : { - "revision" : "ae4d0b672cd7094ae513097c617951a5ac714418", - "version" : "0.50.8" - } - } - ], - "version" : 2 -} diff --git a/Package.swift b/Package.swift index 81b6b807f..c72e7e205 100644 --- a/Package.swift +++ b/Package.swift @@ -19,9 +19,6 @@ let package = Package( targets: ["BlueprintUICommonControls"] ), ], - dependencies: [ - .package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.50.8"), - ], targets: [ .target( name: "BlueprintUI", diff --git a/README.md b/README.md index b4207d636..8ea7d6016 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,26 @@ target MyTarget do end ``` +## Local Development + +This project uses [Mise](https://mise.jdx.dev/) and [Tuist](https://tuist.io/) to generate a project for local development. Follow the steps below for the recommended setup for zsh. + +```sh +# install mise +brew install mise +# add mise activation line to your zshrc +echo 'eval "$(mise activate zsh)"' >> ~/.zshrc +# load mise into your shell +source ~/.zshrc +# install dependencies +mise install + +# only necessary for first setup or after changing dependencies +tuist install --path SampleApp +# generates and opens the Xcode project +tuist generate --path SampleApp +``` + --- [Release instructions](./RELEASING.md) diff --git a/SampleApp/Podfile b/SampleApp/Podfile deleted file mode 100644 index f9f534856..000000000 --- a/SampleApp/Podfile +++ /dev/null @@ -1,28 +0,0 @@ -platform :ios, '15.0' - -project 'SampleApp.xcodeproj' - -def blueprint_pods - pod 'BlueprintUI', :path => '../BlueprintUI.podspec', :testspecs => ['Tests'] - pod 'BlueprintUICommonControls', :path => '../BlueprintUICommonControls.podspec' -end - -target 'SampleApp' do - blueprint_pods -end - -target 'Tutorial 1' do - blueprint_pods -end - -target 'Tutorial 1 (Completed)' do - blueprint_pods -end - -target 'Tutorial 2' do - blueprint_pods -end - -target 'Tutorial 2 (Completed)' do - blueprint_pods -end diff --git a/SampleApp/Podfile.lock b/SampleApp/Podfile.lock deleted file mode 100644 index 7f0f9cbe8..000000000 --- a/SampleApp/Podfile.lock +++ /dev/null @@ -1,24 +0,0 @@ -PODS: - - BlueprintUI (5.1.0) - - BlueprintUI/Tests (5.1.0) - - BlueprintUICommonControls (5.1.0): - - BlueprintUI (= 5.1.0) - -DEPENDENCIES: - - BlueprintUI (from `../BlueprintUI.podspec`) - - BlueprintUI/Tests (from `../BlueprintUI.podspec`) - - BlueprintUICommonControls (from `../BlueprintUICommonControls.podspec`) - -EXTERNAL SOURCES: - BlueprintUI: - :path: "../BlueprintUI.podspec" - BlueprintUICommonControls: - :path: "../BlueprintUICommonControls.podspec" - -SPEC CHECKSUMS: - BlueprintUI: 9ba3799699c813cf86165fc36e646bb10e7e5b47 - BlueprintUICommonControls: 91307b32a90175365c389ef0a033c516bd56feb7 - -PODFILE CHECKSUM: 1cffac4623851f31dc42270ba99701e3825e6d67 - -COCOAPODS: 1.14.3 diff --git a/SampleApp/Project.swift b/SampleApp/Project.swift new file mode 100644 index 000000000..9718a5dec --- /dev/null +++ b/SampleApp/Project.swift @@ -0,0 +1,57 @@ +import Foundation +import ProjectDescription +import ProjectDescriptionHelpers + +let project = Project( + name: "Development", + settings: .settings(base: ["ENABLE_MODULE_VERIFIER": "YES"]), + targets: [ + + .app( + name: "SampleApp", + sources: ["Sources/**"] + ), + + .app( + name: "Tutorial 1", + sources: ["Tutorials/Tutorial 1/**"] + ), + .app( + name: "Tutorial 1 (Completed)", + sources: ["Tutorials/Tutorial 1 (Completed)/**"] + ), + .app( + name: "Tutorial 2", + sources: ["Tutorials/Tutorial 2/**"] + ), + .app( + name: "Tutorial 2 (Completed)", + sources: ["Tutorials/Tutorial 2 (Completed)/**"] + ), + + // These tests are duplicates of the test definitions in the root Package.swift, but Tuist + // does not currently support creating targets for tests in SwiftPM dependencies. See + // https://github.com/tuist/tuist/issues/5912 + + .unitTest(for: "BlueprintUI"), + .unitTest( + for: "BlueprintUICommonControls", + resources: [ + .glob( + pattern: "../BlueprintUICommonControls/Tests/Sources/Resources/*" + ), + ] + ), + ], + schemes: [ + .scheme( + name: "UnitTests", + testAction: .targets( + [ + "BlueprintUI-Tests", + "BlueprintUICommonControls-Tests", + ] + ) + ), + ] +) diff --git a/SampleApp/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json b/SampleApp/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d8db8d65f..000000000 --- a/SampleApp/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "1x" - }, - { - "idiom" : "ipad", - "size" : "76x76", - "scale" : "2x" - }, - { - "idiom" : "ipad", - "size" : "83.5x83.5", - "scale" : "2x" - }, - { - "idiom" : "ios-marketing", - "size" : "1024x1024", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/SampleApp/Resources/Assets.xcassets/Contents.json b/SampleApp/Resources/Assets.xcassets/Contents.json deleted file mode 100644 index da4a164c9..000000000 --- a/SampleApp/Resources/Assets.xcassets/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/SampleApp/Resources/Base.lproj/LaunchScreen.storyboard b/SampleApp/Resources/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index bfa361294..000000000 --- a/SampleApp/Resources/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SampleApp/Resources/Info.plist b/SampleApp/Resources/Info.plist deleted file mode 100644 index 4222ac2dd..000000000 --- a/SampleApp/Resources/Info.plist +++ /dev/null @@ -1,43 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - - diff --git a/SampleApp/SampleApp.xcodeproj/project.pbxproj b/SampleApp/SampleApp.xcodeproj/project.pbxproj deleted file mode 100644 index 183fd44c0..000000000 --- a/SampleApp/SampleApp.xcodeproj/project.pbxproj +++ /dev/null @@ -1,1024 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 54; - objects = { - -/* Begin PBXBuildFile section */ - 0A50E8DB24A685DA0049705B /* RootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A50E8DA24A685DA0049705B /* RootViewController.swift */; }; - 0AEA09B32428360500F9ED0C /* ScrollViewKeyboardViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AEA09B22428360500F9ED0C /* ScrollViewKeyboardViewController.swift */; }; - 0AEF0C4E24463B880092248C /* XcodePreviewDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AEF0C4D24463B880092248C /* XcodePreviewDemo.swift */; }; - 0AF36345246266AF0027E172 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 0AF36342246266AF0027E172 /* README.md */; }; - 0AF36346246266AF0027E172 /* RELEASING.md in Resources */ = {isa = PBXBuildFile; fileRef = 0AF36343246266AF0027E172 /* RELEASING.md */; }; - 0AF36347246266AF0027E172 /* CHANGELOG.md in Resources */ = {isa = PBXBuildFile; fileRef = 0AF36344246266AF0027E172 /* CHANGELOG.md */; }; - 2009E82B0B9D98A685E8637B /* libPods-Tutorial 1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 237956659E4F5F4AEE53B303 /* libPods-Tutorial 1.a */; }; - 4EE23713D657C21C6806E771 /* libPods-SampleApp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ADDB22E4D9B4379A15C5AF69 /* libPods-SampleApp.a */; }; - 6B58C7884AE69FA55EA64E57 /* libPods-Tutorial 2 (Completed).a in Frameworks */ = {isa = PBXBuildFile; fileRef = 187E50F5B5395EA0C0BCA8B2 /* libPods-Tutorial 2 (Completed).a */; }; - 7A4B688424DB3BE300E10D7A /* ResponsiveViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4B688324DB3BE300E10D7A /* ResponsiveViewController.swift */; }; - 83B605572BA0ECC700C867CC /* AccessibilityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83B605562BA0ECC700C867CC /* AccessibilityViewController.swift */; }; - 97545519223C12E9003E353F /* PostsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97545510223C12E9003E353F /* PostsViewController.swift */; }; - 9754551A223C12E9003E353F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97545511223C12E9003E353F /* AppDelegate.swift */; }; - 9754551B223C12E9003E353F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97545513223C12E9003E353F /* Assets.xcassets */; }; - 9754551C223C12E9003E353F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97545514223C12E9003E353F /* LaunchScreen.storyboard */; }; - 9796EC42224D1D2000E729F3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97545513223C12E9003E353F /* Assets.xcassets */; }; - 9796EC43224D1D2000E729F3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97545514223C12E9003E353F /* LaunchScreen.storyboard */; }; - 9796EC4A224D1D5B00E729F3 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9796EC49224D1D5A00E729F3 /* ViewController.swift */; }; - 9796EC4B224D1D6000E729F3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9796EC39224D1CFE00E729F3 /* AppDelegate.swift */; }; - 9796EC5A224DB3BF00E729F3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97545513223C12E9003E353F /* Assets.xcassets */; }; - 9796EC5B224DB3BF00E729F3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97545514223C12E9003E353F /* LaunchScreen.storyboard */; }; - 9796EC69224DB3C500E729F3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97545513223C12E9003E353F /* Assets.xcassets */; }; - 9796EC6A224DB3C500E729F3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97545514223C12E9003E353F /* LaunchScreen.storyboard */; }; - 9796EC70224DB3DF00E729F3 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9796EC50224DB3B500E729F3 /* ViewController.swift */; }; - 9796EC71224DB3DF00E729F3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9796EC51224DB3B500E729F3 /* AppDelegate.swift */; }; - 9796EC72224DB3E300E729F3 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9796EC4D224DB3B500E729F3 /* ViewController.swift */; }; - 9796EC73224DB3E300E729F3 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9796EC4E224DB3B500E729F3 /* AppDelegate.swift */; }; - 9796EC75224DB41500E729F3 /* ReceiptElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9796EC74224DB41500E729F3 /* ReceiptElement.swift */; }; - 9796EC7A224DB90B00E729F3 /* LineItemElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9796EC79224DB90B00E729F3 /* LineItemElement.swift */; }; - 9796EC7C224DBE0000E729F3 /* RuleElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9796EC7B224DBE0000E729F3 /* RuleElement.swift */; }; - 9796EC80224DD67900E729F3 /* Purchase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9796EC7F224DD67900E729F3 /* Purchase.swift */; }; - 979F49ED224D1BD300A3C5D4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97545513223C12E9003E353F /* Assets.xcassets */; }; - 979F49EE224D1BD300A3C5D4 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97545514223C12E9003E353F /* LaunchScreen.storyboard */; }; - 979F49F4224D1BF200A3C5D4 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 979F49E4224D1B6C00A3C5D4 /* AppDelegate.swift */; }; - A7611DAC06D59DA383B1870E /* libPods-Tutorial 1 (Completed).a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B42C382728D022D1B556802 /* libPods-Tutorial 1 (Completed).a */; }; - C223C14227693D65002AF5C4 /* TextLinkViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C223C14127693D65002AF5C4 /* TextLinkViewController.swift */; }; - D72C504447FA36584122770B /* libPods-Tutorial 2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5FCF8B77DD126D724029EB47 /* libPods-Tutorial 2.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - 0A50E8DA24A685DA0049705B /* RootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootViewController.swift; sourceTree = ""; }; - 0AEA09B22428360500F9ED0C /* ScrollViewKeyboardViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollViewKeyboardViewController.swift; sourceTree = ""; }; - 0AEF0C4D24463B880092248C /* XcodePreviewDemo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcodePreviewDemo.swift; sourceTree = ""; }; - 0AF36342246266AF0027E172 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; - 0AF36343246266AF0027E172 /* RELEASING.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = RELEASING.md; path = ../RELEASING.md; sourceTree = ""; }; - 0AF36344246266AF0027E172 /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = CHANGELOG.md; path = ../CHANGELOG.md; sourceTree = ""; }; - 0DA29F056002872418F7D2C9 /* Pods-SampleApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleApp.debug.xcconfig"; path = "Target Support Files/Pods-SampleApp/Pods-SampleApp.debug.xcconfig"; sourceTree = ""; }; - 187E50F5B5395EA0C0BCA8B2 /* libPods-Tutorial 2 (Completed).a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tutorial 2 (Completed).a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 1A147478D522E763BFC19F37 /* Pods-Tutorial 2 (Completed).debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tutorial 2 (Completed).debug.xcconfig"; path = "Target Support Files/Pods-Tutorial 2 (Completed)/Pods-Tutorial 2 (Completed).debug.xcconfig"; sourceTree = ""; }; - 237956659E4F5F4AEE53B303 /* libPods-Tutorial 1.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tutorial 1.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 2B42C382728D022D1B556802 /* libPods-Tutorial 1 (Completed).a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tutorial 1 (Completed).a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 2C24AF26BD9F959834BD0A25 /* Pods-Tutorial1.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tutorial1.debug.xcconfig"; path = "../../Pods/Target Support Files/Pods-Tutorial1/Pods-Tutorial1.debug.xcconfig"; sourceTree = ""; }; - 2F2123B124F06446978E629D /* Pods-SampleApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleApp.release.xcconfig"; path = "Target Support Files/Pods-SampleApp/Pods-SampleApp.release.xcconfig"; sourceTree = ""; }; - 5FCF8B77DD126D724029EB47 /* libPods-Tutorial 2.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Tutorial 2.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 6D524EC9EF929FCE2F54EC85 /* Pods-Tutorial1.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tutorial1.release.xcconfig"; path = "../../Pods/Target Support Files/Pods-Tutorial1/Pods-Tutorial1.release.xcconfig"; sourceTree = ""; }; - 70E2DBB7A375C527D66B2643 /* Pods-Tutorial 1.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tutorial 1.debug.xcconfig"; path = "Target Support Files/Pods-Tutorial 1/Pods-Tutorial 1.debug.xcconfig"; sourceTree = ""; }; - 7A4B688324DB3BE300E10D7A /* ResponsiveViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResponsiveViewController.swift; sourceTree = ""; }; - 7A5624391C38E617246C4356 /* Pods-Tutorial 2.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tutorial 2.debug.xcconfig"; path = "Target Support Files/Pods-Tutorial 2/Pods-Tutorial 2.debug.xcconfig"; sourceTree = ""; }; - 7EA5EE31421ECA2CA9457450 /* Pods-Tutorial 2.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tutorial 2.release.xcconfig"; path = "Target Support Files/Pods-Tutorial 2/Pods-Tutorial 2.release.xcconfig"; sourceTree = ""; }; - 83B605562BA0ECC700C867CC /* AccessibilityViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityViewController.swift; sourceTree = ""; }; - 8501C9E99E00354D89175E65 /* Pods-Tutorial 1.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tutorial 1.release.xcconfig"; path = "Target Support Files/Pods-Tutorial 1/Pods-Tutorial 1.release.xcconfig"; sourceTree = ""; }; - 975454FA223C1289003E353F /* SampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97545510223C12E9003E353F /* PostsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostsViewController.swift; sourceTree = ""; }; - 97545511223C12E9003E353F /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 97545513223C12E9003E353F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97545515223C12E9003E353F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97545518223C12E9003E353F /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 9796EC39224D1CFE00E729F3 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 9796EC47224D1D2000E729F3 /* Tutorial 1 (Completed).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Tutorial 1 (Completed).app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 9796EC49224D1D5A00E729F3 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 9796EC4D224DB3B500E729F3 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 9796EC4E224DB3B500E729F3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 9796EC50224DB3B500E729F3 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 9796EC51224DB3B500E729F3 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 9796EC5F224DB3BF00E729F3 /* Tutorial 2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Tutorial 2.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 9796EC6E224DB3C500E729F3 /* Tutorial 2 (Completed).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Tutorial 2 (Completed).app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 9796EC74224DB41500E729F3 /* ReceiptElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReceiptElement.swift; sourceTree = ""; }; - 9796EC79224DB90B00E729F3 /* LineItemElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LineItemElement.swift; sourceTree = ""; }; - 9796EC7B224DBE0000E729F3 /* RuleElement.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuleElement.swift; sourceTree = ""; }; - 9796EC7F224DD67900E729F3 /* Purchase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Purchase.swift; sourceTree = ""; }; - 979F49E4224D1B6C00A3C5D4 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 979F49F2224D1BD300A3C5D4 /* Tutorial 1.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Tutorial 1.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - 9D59D92E955A10C9F7EF0730 /* Pods-Tutorial 2 (Completed).release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tutorial 2 (Completed).release.xcconfig"; path = "Target Support Files/Pods-Tutorial 2 (Completed)/Pods-Tutorial 2 (Completed).release.xcconfig"; sourceTree = ""; }; - ADDB22E4D9B4379A15C5AF69 /* libPods-SampleApp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-SampleApp.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - C223C14127693D65002AF5C4 /* TextLinkViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextLinkViewController.swift; sourceTree = ""; }; - CC5FC85BE57034BE39916388 /* Pods-Tutorial 1 (Completed).debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tutorial 1 (Completed).debug.xcconfig"; path = "Target Support Files/Pods-Tutorial 1 (Completed)/Pods-Tutorial 1 (Completed).debug.xcconfig"; sourceTree = ""; }; - F211AAFE0FF4DC614FC65630 /* Pods-Tutorial 1 (Completed).release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tutorial 1 (Completed).release.xcconfig"; path = "Target Support Files/Pods-Tutorial 1 (Completed)/Pods-Tutorial 1 (Completed).release.xcconfig"; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 975454F7223C1289003E353F /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 4EE23713D657C21C6806E771 /* libPods-SampleApp.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9796EC3F224D1D2000E729F3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - A7611DAC06D59DA383B1870E /* libPods-Tutorial 1 (Completed).a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9796EC57224DB3BF00E729F3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - D72C504447FA36584122770B /* libPods-Tutorial 2.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9796EC66224DB3C500E729F3 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 6B58C7884AE69FA55EA64E57 /* libPods-Tutorial 2 (Completed).a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 979F49EA224D1BD300A3C5D4 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 2009E82B0B9D98A685E8637B /* libPods-Tutorial 1.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 69943C07C9B6B3DCFC875540 /* Frameworks */ = { - isa = PBXGroup; - children = ( - ADDB22E4D9B4379A15C5AF69 /* libPods-SampleApp.a */, - 237956659E4F5F4AEE53B303 /* libPods-Tutorial 1.a */, - 2B42C382728D022D1B556802 /* libPods-Tutorial 1 (Completed).a */, - 5FCF8B77DD126D724029EB47 /* libPods-Tutorial 2.a */, - 187E50F5B5395EA0C0BCA8B2 /* libPods-Tutorial 2 (Completed).a */, - ); - name = Frameworks; - sourceTree = ""; - }; - 975454F1223C1289003E353F = { - isa = PBXGroup; - children = ( - 0AF36344246266AF0027E172 /* CHANGELOG.md */, - 0AF36342246266AF0027E172 /* README.md */, - 0AF36343246266AF0027E172 /* RELEASING.md */, - 97545512223C12E9003E353F /* Resources */, - 9754550F223C12E9003E353F /* Sources */, - 979F49E1224D1B4500A3C5D4 /* Tutorials */, - 975454FB223C1289003E353F /* Products */, - BC66766C3ED64DAEF49CBABD /* Pods */, - 69943C07C9B6B3DCFC875540 /* Frameworks */, - ); - sourceTree = ""; - }; - 975454FB223C1289003E353F /* Products */ = { - isa = PBXGroup; - children = ( - 975454FA223C1289003E353F /* SampleApp.app */, - 979F49F2224D1BD300A3C5D4 /* Tutorial 1.app */, - 9796EC47224D1D2000E729F3 /* Tutorial 1 (Completed).app */, - 9796EC5F224DB3BF00E729F3 /* Tutorial 2.app */, - 9796EC6E224DB3C500E729F3 /* Tutorial 2 (Completed).app */, - ); - name = Products; - sourceTree = ""; - }; - 9754550F223C12E9003E353F /* Sources */ = { - isa = PBXGroup; - children = ( - 0A50E8DA24A685DA0049705B /* RootViewController.swift */, - 97545510223C12E9003E353F /* PostsViewController.swift */, - 83B605562BA0ECC700C867CC /* AccessibilityViewController.swift */, - C223C14127693D65002AF5C4 /* TextLinkViewController.swift */, - 7A4B688324DB3BE300E10D7A /* ResponsiveViewController.swift */, - 0AEA09B22428360500F9ED0C /* ScrollViewKeyboardViewController.swift */, - 97545511223C12E9003E353F /* AppDelegate.swift */, - 0AEF0C4D24463B880092248C /* XcodePreviewDemo.swift */, - ); - path = Sources; - sourceTree = ""; - }; - 97545512223C12E9003E353F /* Resources */ = { - isa = PBXGroup; - children = ( - 97545513223C12E9003E353F /* Assets.xcassets */, - 97545514223C12E9003E353F /* LaunchScreen.storyboard */, - 97545518223C12E9003E353F /* Info.plist */, - ); - path = Resources; - sourceTree = ""; - }; - 9796EC38224D1CFD00E729F3 /* Tutorial 1 (Completed) */ = { - isa = PBXGroup; - children = ( - 9796EC39224D1CFE00E729F3 /* AppDelegate.swift */, - 9796EC49224D1D5A00E729F3 /* ViewController.swift */, - ); - path = "Tutorial 1 (Completed)"; - sourceTree = ""; - }; - 9796EC4C224DB3B500E729F3 /* Tutorial 2 (Completed) */ = { - isa = PBXGroup; - children = ( - 9796EC7F224DD67900E729F3 /* Purchase.swift */, - 9796EC4D224DB3B500E729F3 /* ViewController.swift */, - 9796EC4E224DB3B500E729F3 /* AppDelegate.swift */, - 9796EC74224DB41500E729F3 /* ReceiptElement.swift */, - 9796EC79224DB90B00E729F3 /* LineItemElement.swift */, - 9796EC7B224DBE0000E729F3 /* RuleElement.swift */, - ); - path = "Tutorial 2 (Completed)"; - sourceTree = ""; - }; - 9796EC4F224DB3B500E729F3 /* Tutorial 2 */ = { - isa = PBXGroup; - children = ( - 9796EC50224DB3B500E729F3 /* ViewController.swift */, - 9796EC51224DB3B500E729F3 /* AppDelegate.swift */, - ); - path = "Tutorial 2"; - sourceTree = ""; - }; - 979F49E1224D1B4500A3C5D4 /* Tutorials */ = { - isa = PBXGroup; - children = ( - 979F49E2224D1B4F00A3C5D4 /* Tutorial1 */, - 9796EC38224D1CFD00E729F3 /* Tutorial 1 (Completed) */, - 9796EC4F224DB3B500E729F3 /* Tutorial 2 */, - 9796EC4C224DB3B500E729F3 /* Tutorial 2 (Completed) */, - ); - path = Tutorials; - sourceTree = ""; - }; - 979F49E2224D1B4F00A3C5D4 /* Tutorial1 */ = { - isa = PBXGroup; - children = ( - 979F49E4224D1B6C00A3C5D4 /* AppDelegate.swift */, - ); - name = Tutorial1; - path = "Tutorial 1"; - sourceTree = ""; - }; - BC66766C3ED64DAEF49CBABD /* Pods */ = { - isa = PBXGroup; - children = ( - 0DA29F056002872418F7D2C9 /* Pods-SampleApp.debug.xcconfig */, - 2F2123B124F06446978E629D /* Pods-SampleApp.release.xcconfig */, - 2C24AF26BD9F959834BD0A25 /* Pods-Tutorial1.debug.xcconfig */, - 6D524EC9EF929FCE2F54EC85 /* Pods-Tutorial1.release.xcconfig */, - 70E2DBB7A375C527D66B2643 /* Pods-Tutorial 1.debug.xcconfig */, - 8501C9E99E00354D89175E65 /* Pods-Tutorial 1.release.xcconfig */, - CC5FC85BE57034BE39916388 /* Pods-Tutorial 1 (Completed).debug.xcconfig */, - F211AAFE0FF4DC614FC65630 /* Pods-Tutorial 1 (Completed).release.xcconfig */, - 7A5624391C38E617246C4356 /* Pods-Tutorial 2.debug.xcconfig */, - 7EA5EE31421ECA2CA9457450 /* Pods-Tutorial 2.release.xcconfig */, - 1A147478D522E763BFC19F37 /* Pods-Tutorial 2 (Completed).debug.xcconfig */, - 9D59D92E955A10C9F7EF0730 /* Pods-Tutorial 2 (Completed).release.xcconfig */, - ); - path = Pods; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 975454F9223C1289003E353F /* SampleApp */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9754550C223C128B003E353F /* Build configuration list for PBXNativeTarget "SampleApp" */; - buildPhases = ( - 6DD21A891D7570215C38D645 /* [CP] Check Pods Manifest.lock */, - 975454F6223C1289003E353F /* Sources */, - 975454F7223C1289003E353F /* Frameworks */, - 975454F8223C1289003E353F /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = SampleApp; - productName = SampleApp; - productReference = 975454FA223C1289003E353F /* SampleApp.app */; - productType = "com.apple.product-type.application"; - }; - 9796EC3B224D1D2000E729F3 /* Tutorial 1 (Completed) */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9796EC44224D1D2000E729F3 /* Build configuration list for PBXNativeTarget "Tutorial 1 (Completed)" */; - buildPhases = ( - 9796EC3C224D1D2000E729F3 /* [CP] Check Pods Manifest.lock */, - 9796EC3D224D1D2000E729F3 /* Sources */, - 9796EC3F224D1D2000E729F3 /* Frameworks */, - 9796EC41224D1D2000E729F3 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Tutorial 1 (Completed)"; - productName = SampleApp; - productReference = 9796EC47224D1D2000E729F3 /* Tutorial 1 (Completed).app */; - productType = "com.apple.product-type.application"; - }; - 9796EC52224DB3BF00E729F3 /* Tutorial 2 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9796EC5C224DB3BF00E729F3 /* Build configuration list for PBXNativeTarget "Tutorial 2" */; - buildPhases = ( - 9796EC53224DB3BF00E729F3 /* [CP] Check Pods Manifest.lock */, - 9796EC54224DB3BF00E729F3 /* Sources */, - 9796EC57224DB3BF00E729F3 /* Frameworks */, - 9796EC59224DB3BF00E729F3 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Tutorial 2"; - productName = SampleApp; - productReference = 9796EC5F224DB3BF00E729F3 /* Tutorial 2.app */; - productType = "com.apple.product-type.application"; - }; - 9796EC61224DB3C500E729F3 /* Tutorial 2 (Completed) */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9796EC6B224DB3C500E729F3 /* Build configuration list for PBXNativeTarget "Tutorial 2 (Completed)" */; - buildPhases = ( - 9796EC62224DB3C500E729F3 /* [CP] Check Pods Manifest.lock */, - 9796EC63224DB3C500E729F3 /* Sources */, - 9796EC66224DB3C500E729F3 /* Frameworks */, - 9796EC68224DB3C500E729F3 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Tutorial 2 (Completed)"; - productName = SampleApp; - productReference = 9796EC6E224DB3C500E729F3 /* Tutorial 2 (Completed).app */; - productType = "com.apple.product-type.application"; - }; - 979F49E5224D1BD300A3C5D4 /* Tutorial 1 */ = { - isa = PBXNativeTarget; - buildConfigurationList = 979F49EF224D1BD300A3C5D4 /* Build configuration list for PBXNativeTarget "Tutorial 1" */; - buildPhases = ( - 5C44B0027B3C66DF83F44D0A /* [CP] Check Pods Manifest.lock */, - 979F49E7224D1BD300A3C5D4 /* Sources */, - 979F49EA224D1BD300A3C5D4 /* Frameworks */, - 979F49EC224D1BD300A3C5D4 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "Tutorial 1"; - productName = SampleApp; - productReference = 979F49F2224D1BD300A3C5D4 /* Tutorial 1.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 975454F2223C1289003E353F /* Project object */ = { - isa = PBXProject; - attributes = { - BuildIndependentTargetsInParallel = YES; - LastSwiftUpdateCheck = 1010; - LastUpgradeCheck = 1510; - ORGANIZATIONNAME = Square; - TargetAttributes = { - 975454F9223C1289003E353F = { - CreatedOnToolsVersion = 10.1; - LastSwiftMigration = 1020; - }; - 9796EC3B224D1D2000E729F3 = { - LastSwiftMigration = 1020; - }; - 9796EC52224DB3BF00E729F3 = { - LastSwiftMigration = 1020; - }; - 9796EC61224DB3C500E729F3 = { - LastSwiftMigration = 1020; - }; - 979F49E5224D1BD300A3C5D4 = { - LastSwiftMigration = 1020; - }; - }; - }; - buildConfigurationList = 975454F5223C1289003E353F /* Build configuration list for PBXProject "SampleApp" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 975454F1223C1289003E353F; - productRefGroup = 975454FB223C1289003E353F /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 975454F9223C1289003E353F /* SampleApp */, - 979F49E5224D1BD300A3C5D4 /* Tutorial 1 */, - 9796EC3B224D1D2000E729F3 /* Tutorial 1 (Completed) */, - 9796EC52224DB3BF00E729F3 /* Tutorial 2 */, - 9796EC61224DB3C500E729F3 /* Tutorial 2 (Completed) */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 975454F8223C1289003E353F /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0AF36345246266AF0027E172 /* README.md in Resources */, - 0AF36347246266AF0027E172 /* CHANGELOG.md in Resources */, - 0AF36346246266AF0027E172 /* RELEASING.md in Resources */, - 9754551B223C12E9003E353F /* Assets.xcassets in Resources */, - 9754551C223C12E9003E353F /* LaunchScreen.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9796EC41224D1D2000E729F3 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 9796EC42224D1D2000E729F3 /* Assets.xcassets in Resources */, - 9796EC43224D1D2000E729F3 /* LaunchScreen.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9796EC59224DB3BF00E729F3 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 9796EC5A224DB3BF00E729F3 /* Assets.xcassets in Resources */, - 9796EC5B224DB3BF00E729F3 /* LaunchScreen.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9796EC68224DB3C500E729F3 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 9796EC69224DB3C500E729F3 /* Assets.xcassets in Resources */, - 9796EC6A224DB3C500E729F3 /* LaunchScreen.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 979F49EC224D1BD300A3C5D4 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 979F49ED224D1BD300A3C5D4 /* Assets.xcassets in Resources */, - 979F49EE224D1BD300A3C5D4 /* LaunchScreen.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 5C44B0027B3C66DF83F44D0A /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Tutorial 1-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 6DD21A891D7570215C38D645 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-SampleApp-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 9796EC3C224D1D2000E729F3 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Tutorial 1 (Completed)-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 9796EC53224DB3BF00E729F3 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Tutorial 2-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; - 9796EC62224DB3C500E729F3 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Tutorial 2 (Completed)-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 975454F6223C1289003E353F /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 0A50E8DB24A685DA0049705B /* RootViewController.swift in Sources */, - 83B605572BA0ECC700C867CC /* AccessibilityViewController.swift in Sources */, - 9754551A223C12E9003E353F /* AppDelegate.swift in Sources */, - 97545519223C12E9003E353F /* PostsViewController.swift in Sources */, - 0AEA09B32428360500F9ED0C /* ScrollViewKeyboardViewController.swift in Sources */, - 7A4B688424DB3BE300E10D7A /* ResponsiveViewController.swift in Sources */, - 0AEF0C4E24463B880092248C /* XcodePreviewDemo.swift in Sources */, - C223C14227693D65002AF5C4 /* TextLinkViewController.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9796EC3D224D1D2000E729F3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 9796EC4B224D1D6000E729F3 /* AppDelegate.swift in Sources */, - 9796EC4A224D1D5B00E729F3 /* ViewController.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9796EC54224DB3BF00E729F3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 9796EC71224DB3DF00E729F3 /* AppDelegate.swift in Sources */, - 9796EC70224DB3DF00E729F3 /* ViewController.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 9796EC63224DB3C500E729F3 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 9796EC7A224DB90B00E729F3 /* LineItemElement.swift in Sources */, - 9796EC73224DB3E300E729F3 /* AppDelegate.swift in Sources */, - 9796EC7C224DBE0000E729F3 /* RuleElement.swift in Sources */, - 9796EC72224DB3E300E729F3 /* ViewController.swift in Sources */, - 9796EC75224DB41500E729F3 /* ReceiptElement.swift in Sources */, - 9796EC80224DD67900E729F3 /* Purchase.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 979F49E7224D1BD300A3C5D4 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 979F49F4224D1BF200A3C5D4 /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 97545514223C12E9003E353F /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97545515223C12E9003E353F /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 9754550A223C128B003E353F /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - 9754550B223C128B003E353F /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_USER_SCRIPT_SANDBOXING = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - SDKROOT = iphoneos; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 9754550D223C128B003E353F /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 0DA29F056002872418F7D2C9 /* Pods-SampleApp.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.blueprint-sample-app.SampleApp"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 9754550E223C128B003E353F /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 2F2123B124F06446978E629D /* Pods-SampleApp.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.blueprint-sample-app.SampleApp"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 9796EC45224D1D2000E729F3 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = CC5FC85BE57034BE39916388 /* Pods-Tutorial 1 (Completed).debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.blueprint-sample-app.Tutorial1Completed"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 9796EC46224D1D2000E729F3 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = F211AAFE0FF4DC614FC65630 /* Pods-Tutorial 1 (Completed).release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.blueprint-sample-app.Tutorial1Completed"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 9796EC5D224DB3BF00E729F3 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7A5624391C38E617246C4356 /* Pods-Tutorial 2.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.blueprint-sample-app.Tutorial2"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 9796EC5E224DB3BF00E729F3 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7EA5EE31421ECA2CA9457450 /* Pods-Tutorial 2.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.blueprint-sample-app.Tutorial2"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 9796EC6C224DB3C500E729F3 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1A147478D522E763BFC19F37 /* Pods-Tutorial 2 (Completed).debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.blueprint-sample-app.Tutorial2Completed"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 9796EC6D224DB3C500E729F3 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9D59D92E955A10C9F7EF0730 /* Pods-Tutorial 2 (Completed).release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.blueprint-sample-app.Tutorial2Completed"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; - 979F49F0224D1BD300A3C5D4 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 70E2DBB7A375C527D66B2643 /* Pods-Tutorial 1.debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.blueprint-sample-app.Tutorial1"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 979F49F1224D1BD300A3C5D4 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 8501C9E99E00354D89175E65 /* Pods-Tutorial 1.release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = ""; - INFOPLIST_FILE = "$(SRCROOT)/Resources/Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - ); - PRODUCT_BUNDLE_IDENTIFIER = "com.squareup.blueprint-sample-app.Tutorial1"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 975454F5223C1289003E353F /* Build configuration list for PBXProject "SampleApp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9754550A223C128B003E353F /* Debug */, - 9754550B223C128B003E353F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 9754550C223C128B003E353F /* Build configuration list for PBXNativeTarget "SampleApp" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9754550D223C128B003E353F /* Debug */, - 9754550E223C128B003E353F /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 9796EC44224D1D2000E729F3 /* Build configuration list for PBXNativeTarget "Tutorial 1 (Completed)" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9796EC45224D1D2000E729F3 /* Debug */, - 9796EC46224D1D2000E729F3 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 9796EC5C224DB3BF00E729F3 /* Build configuration list for PBXNativeTarget "Tutorial 2" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9796EC5D224DB3BF00E729F3 /* Debug */, - 9796EC5E224DB3BF00E729F3 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 9796EC6B224DB3C500E729F3 /* Build configuration list for PBXNativeTarget "Tutorial 2 (Completed)" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9796EC6C224DB3C500E729F3 /* Debug */, - 9796EC6D224DB3C500E729F3 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 979F49EF224D1BD300A3C5D4 /* Build configuration list for PBXNativeTarget "Tutorial 1" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 979F49F0224D1BD300A3C5D4 /* Debug */, - 979F49F1224D1BD300A3C5D4 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 975454F2223C1289003E353F /* Project object */; -} diff --git a/SampleApp/SampleApp.xcodeproj/xcshareddata/xcschemes/SampleApp.xcscheme b/SampleApp/SampleApp.xcodeproj/xcshareddata/xcschemes/SampleApp.xcscheme deleted file mode 100644 index 0195d6916..000000000 --- a/SampleApp/SampleApp.xcodeproj/xcshareddata/xcschemes/SampleApp.xcscheme +++ /dev/null @@ -1,153 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SampleApp/SampleApp.xcodeproj/xcshareddata/xcschemes/Tutorial 1 (Completed).xcscheme b/SampleApp/SampleApp.xcodeproj/xcshareddata/xcschemes/Tutorial 1 (Completed).xcscheme deleted file mode 100644 index a9a239168..000000000 --- a/SampleApp/SampleApp.xcodeproj/xcshareddata/xcschemes/Tutorial 1 (Completed).xcscheme +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SampleApp/SampleApp.xcodeproj/xcshareddata/xcschemes/Tutorial 1.xcscheme b/SampleApp/SampleApp.xcodeproj/xcshareddata/xcschemes/Tutorial 1.xcscheme deleted file mode 100644 index 1da6aa599..000000000 --- a/SampleApp/SampleApp.xcodeproj/xcshareddata/xcschemes/Tutorial 1.xcscheme +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SampleApp/Sources/PostsViewController.swift b/SampleApp/Sources/PostsViewController.swift index c962ebca8..0f0bc93e3 100644 --- a/SampleApp/Sources/PostsViewController.swift +++ b/SampleApp/Sources/PostsViewController.swift @@ -88,9 +88,9 @@ final class PostsViewController: UIViewController { guard let self = self else { return } switch field { case .name: - self.state.entry.authorName = text + state.entry.authorName = text case .body: - self.state.entry.body = text + state.entry.body = text } }, onSubmit: { [weak self] in @@ -142,7 +142,7 @@ fileprivate struct MainView: ProxyElement { $0.contentSize = .fittingHeight $0.alwaysBounceVertical = true $0.keyboardDismissMode = .onDrag - $0.pullToRefreshBehavior = self.pullToRefreshBehavior + $0.pullToRefreshBehavior = pullToRefreshBehavior } .inset(by: environment.safeAreaInsets) .box(background: UIColor(white: 0.95, alpha: 1.0)) @@ -272,7 +272,7 @@ fileprivate struct FeedItemBody: ProxyElement { row.verticalAlignment = .center let name = EnvironmentReader { environment -> Element in - var name = Label(text: self.post.authorName) + var name = Label(text: post.authorName) name.font = UIFont.boldSystemFont(ofSize: 14.0) name.color = environment.feedTheme.authorColor return name diff --git a/SampleApp/Sources/ResponsiveViewController.swift b/SampleApp/Sources/ResponsiveViewController.swift index 9cbe3c544..7816691c8 100644 --- a/SampleApp/Sources/ResponsiveViewController.swift +++ b/SampleApp/Sources/ResponsiveViewController.swift @@ -39,7 +39,7 @@ struct ResponsiveLabel: ProxyElement { var elementRepresentation: Element { GeometryReader { geometry -> Element in - let label = Label(text: self.text) { label in + let label = Label(text: text) { label in label.numberOfLines = 1 } diff --git a/SampleApp/Sources/RootViewController.swift b/SampleApp/Sources/RootViewController.swift index a8c3bbf5e..16ffc8a37 100644 --- a/SampleApp/Sources/RootViewController.swift +++ b/SampleApp/Sources/RootViewController.swift @@ -98,13 +98,13 @@ fileprivate struct DemoItem: ProxyElement { ) ) .tappable { - self.onTap() + onTap() } .decorate(layering: .below, position: .inset(5)) { Box(backgroundColor: .init(white: 0.0, alpha: 0.1), cornerStyle: .rounded(radius: 17)) } .decorate(layering: .above, position: .corner(.topLeft)) { - guard let badge = self.badgeText else { + guard let badge = badgeText else { return Empty() } diff --git a/SampleApp/Tuist/Package.swift b/SampleApp/Tuist/Package.swift new file mode 100644 index 000000000..9f90e9032 --- /dev/null +++ b/SampleApp/Tuist/Package.swift @@ -0,0 +1,10 @@ +// swift-tools-version: 5.9 + +import PackageDescription + +let package = Package( + name: "Development", + dependencies: [ + .package(path: "../../"), + ] +) diff --git a/SampleApp/Tuist/ProjectDescriptionHelpers/Project+Blueprint.swift b/SampleApp/Tuist/ProjectDescriptionHelpers/Project+Blueprint.swift new file mode 100644 index 000000000..afdd4883e --- /dev/null +++ b/SampleApp/Tuist/ProjectDescriptionHelpers/Project+Blueprint.swift @@ -0,0 +1,88 @@ +import Foundation +import ProjectDescription + +public let blueprintBundleIdPrefix = "com.squareup.blueprint" +public let blueprintDestinations: ProjectDescription.Destinations = .iOS +public let blueprintDeploymentTargets: DeploymentTargets = .iOS("15.0") + +public let blueprintDependencies: [TargetDependency] = [ + .external(name: "BlueprintUI"), + .external(name: "BlueprintUICommonControls"), +] + +extension String { + var bundleId: String { + replacing(try! Regex("[^A-Za-z0-9-\\.]")) { _ in "" } + } + + var productName: String { + replacing(try! Regex("[^A-Za-z0-9-\\._]")) { _ in "" } + } +} + +extension Target { + + public static func app( + name: String, + sources: ProjectDescription.SourceFilesList, + resources: ProjectDescription.ResourceFileElements? = nil, + dependencies: [TargetDependency] = blueprintDependencies + ) -> Self { + .target( + name: name, + destinations: blueprintDestinations, + product: .app, + productName: name.productName, + bundleId: "\(blueprintBundleIdPrefix).\(name.bundleId)", + deploymentTargets: blueprintDeploymentTargets, + infoPlist: .extendingDefault( + with: [ + "UILaunchScreen": ["UIColorName": ""], + ] + ), + sources: sources, + resources: resources, + dependencies: dependencies + ) + } + + public static func target( + name: String, + sources: ProjectDescription.SourceFilesList? = nil, + resources: ProjectDescription.ResourceFileElements? = nil, + dependencies: [TargetDependency] = blueprintDependencies + ) -> Self { + .target( + name: name, + destinations: blueprintDestinations, + product: .framework, + bundleId: "\(blueprintBundleIdPrefix).\(name.bundleId)", + deploymentTargets: blueprintDeploymentTargets, + sources: sources ?? "\(name)/Sources/**", + resources: resources, + dependencies: dependencies + ) + } + + public static func unitTest( + for moduleUnderTest: String, + testName: String = "Tests", + sources: ProjectDescription.SourceFilesList? = nil, + resources: ProjectDescription.ResourceFileElements? = nil, + dependencies: [TargetDependency] = blueprintDependencies, + environmentVariables: [String: EnvironmentVariable] = [:] + ) -> Self { + let name = "\(moduleUnderTest)-\(testName)" + return .target( + name: name, + destinations: blueprintDestinations, + product: .unitTests, + bundleId: "\(blueprintBundleIdPrefix).\(name.bundleId)", + deploymentTargets: blueprintDeploymentTargets, + sources: sources ?? "../\(moduleUnderTest)/\(testName)/**", + resources: resources, + dependencies: dependencies, + environmentVariables: environmentVariables + ) + } +} diff --git a/SampleApp/Tutorials/Tutorial 2 (Completed)/LineItemElement.swift b/SampleApp/Tutorials/Tutorial 2 (Completed)/LineItemElement.swift index 8e157b497..9dda2bcda 100644 --- a/SampleApp/Tutorials/Tutorial 2 (Completed)/LineItemElement.swift +++ b/SampleApp/Tutorials/Tutorial 2 (Completed)/LineItemElement.swift @@ -1,5 +1,6 @@ import BlueprintUI import BlueprintUICommonControls +import UIKit struct LineItemElement: ProxyElement { @@ -37,29 +38,29 @@ extension LineItemElement { fileprivate var titleFont: UIFont { switch self { - case .regular: return .systemFont(ofSize: 18.0) - case .bold: return .boldSystemFont(ofSize: 18.0) + case .regular: .systemFont(ofSize: 18.0) + case .bold: .boldSystemFont(ofSize: 18.0) } } fileprivate var titleColor: UIColor { switch self { - case .regular: return .gray - case .bold: return .black + case .regular: .gray + case .bold: .black } } fileprivate var priceFont: UIFont { switch self { - case .regular: return .systemFont(ofSize: 18.0) - case .bold: return .boldSystemFont(ofSize: 18.0) + case .regular: .systemFont(ofSize: 18.0) + case .bold: .boldSystemFont(ofSize: 18.0) } } fileprivate var priceColor: UIColor { switch self { - case .regular: return .black - case .bold: return .black + case .regular: .black + case .bold: .black } } diff --git a/SampleApp/Workspace.swift b/SampleApp/Workspace.swift new file mode 100644 index 000000000..bd342b9cb --- /dev/null +++ b/SampleApp/Workspace.swift @@ -0,0 +1,21 @@ +import ProjectDescription +import ProjectDescriptionHelpers + +let workspace = Workspace( + name: "Development", + projects: ["."], + schemes: [ + // Generate a scheme for each target in Package.swift for convenience + .blueprint("BlueprintUI"), + .blueprint("BlueprintUICommonControls"), + ] +) + +extension Scheme { + public static func blueprint(_ target: String) -> Self { + .scheme( + name: target, + buildAction: .buildAction(targets: [.project(path: "..", target: target)]) + ) + } +} diff --git a/Scripts/git-format-staged b/Scripts/git-format-staged new file mode 100755 index 000000000..0c34d50b7 --- /dev/null +++ b/Scripts/git-format-staged @@ -0,0 +1,281 @@ +#!/usr/bin/env python3 + +# Copied from https://github.com/hallettj/git-format-staged/blob/a4dbdae9df537e6606308c82dd333e9940c9a233/git-format-staged + +# Git command to transform staged files according to a command that accepts file +# content on stdin and produces output on stdout. This command is useful in +# combination with `git add -p` which allows you to stage specific changes in +# a file. This command runs a formatter on the file with staged changes while +# ignoring unstaged changes. +# +# Usage: git-format-staged [OPTION]... [FILE]... +# Example: git-format-staged --formatter 'prettier --stdin-filepath "{}"' '*.js' +# +# Tested with Python versions 3.8 - 3.13. +# +# Original author: Jesse Hallett + +from __future__ import print_function +import argparse +from fnmatch import fnmatch +from gettext import gettext as _ +import os +import re +import subprocess +import sys + +# The string $VERSION is replaced during the publish process. +VERSION = '$VERSION' +PROG = sys.argv[0] + +def info(msg): + print(msg, file=sys.stdout) + +def warn(msg): + print('{}: warning: {}'.format(PROG, msg), file=sys.stderr) + +def fatal(msg): + print('{}: error: {}'.format(PROG, msg), file=sys.stderr) + exit(1) + +def format_staged_files(file_patterns, formatter, git_root, update_working_tree=True, write=True, verbose=False): + try: + output = subprocess.check_output([ + 'git', 'diff-index', + '--cached', + '--diff-filter=AM', # select only file additions and modifications + '--no-renames', + 'HEAD' + ]) + for line in output.splitlines(): + entry = parse_diff(line.decode('utf-8')) + entry_path = normalize_path(entry['src_path'], relative_to=git_root) + if entry['dst_mode'] == '120000': + # Do not process symlinks + continue + if not (matches_some_path(file_patterns, entry_path)): + continue + if format_file_in_index(formatter, entry, update_working_tree=update_working_tree, write=write, verbose=verbose): + info('Reformatted {} with {}'.format(entry['src_path'], formatter)) + except Exception as err: + fatal(str(err)) + +# Run formatter on file in the git index. Creates a new git object with the +# result, and replaces the content of the file in the index with that object. +# Returns hash of the new object if formatting produced any changes. +def format_file_in_index(formatter, diff_entry, update_working_tree=True, write=True, verbose=False): + orig_hash = diff_entry['dst_hash'] + new_hash = format_object(formatter, orig_hash, diff_entry['src_path'], verbose=verbose) + + # If the new hash is the same then the formatter did not make any changes. + if not write or new_hash == orig_hash: + return None + + # If the content of the new object is empty then the formatter did not + # produce any output. We want to abort instead of replacing the file with an + # empty one. + if object_is_empty(new_hash): + return None + + replace_file_in_index(diff_entry, new_hash) + + if update_working_tree: + try: + patch_working_file(diff_entry['src_path'], orig_hash, new_hash) + except Exception as err: + # Errors patching working tree files are not fatal + warn(str(err)) + + return new_hash + +file_path_placeholder = re.compile(r'\{\}') + +# Run formatter on a git blob identified by its hash. Writes output to a new git +# blob, and returns the hash of the new blob. +def format_object(formatter, object_hash, file_path, verbose=False): + get_content = subprocess.Popen( + ['git', 'cat-file', '-p', object_hash], + stdout=subprocess.PIPE + ) + command = re.sub(file_path_placeholder, file_path, formatter) + if verbose: + info(command) + format_content = subprocess.Popen( + command, + shell=True, + stdin=get_content.stdout, + stdout=subprocess.PIPE + ) + write_object = subprocess.Popen( + ['git', 'hash-object', '-w', '--stdin'], + stdin=format_content.stdout, + stdout=subprocess.PIPE + ) + + get_content.stdout.close() + format_content.stdout.close() + + if get_content.wait() != 0: + raise ValueError('unable to read file content from object database: ' + object_hash) + + if format_content.wait() != 0: + raise Exception('formatter exited with non-zero status') # TODO: capture stderr from format command + + new_hash, err = write_object.communicate() + + if write_object.returncode != 0: + raise Exception('unable to write formatted content to object database') + + return new_hash.decode('utf-8').rstrip() + +def object_is_empty(object_hash): + get_content = subprocess.Popen( + ['git', 'cat-file', '-p', object_hash], + stdout=subprocess.PIPE + ) + content, err = get_content.communicate() + + if get_content.returncode != 0: + raise Exception('unable to verify content of formatted object') + + return not content + +def replace_file_in_index(diff_entry, new_object_hash): + subprocess.check_call(['git', 'update-index', + '--cacheinfo', '{},{},{}'.format( + diff_entry['dst_mode'], + new_object_hash, + diff_entry['src_path'] + )]) + +def patch_working_file(path, orig_object_hash, new_object_hash): + patch = subprocess.check_output( + ['git', 'diff', '--no-ext-diff', '--color=never', orig_object_hash, new_object_hash] + ) + + # Substitute object hashes in patch header with path to working tree file + patch_b = patch.replace(orig_object_hash.encode(), path.encode()).replace(new_object_hash.encode(), path.encode()) + + apply_patch = subprocess.Popen( + ['git', 'apply', '-'], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE + ) + + output, err = apply_patch.communicate(input=patch_b) + + if apply_patch.returncode != 0: + raise Exception('could not apply formatting changes to working tree file {}'.format(path)) + +# Format: src_mode dst_mode src_hash dst_hash status/score? src_path dst_path? +diff_pat = re.compile(r'^:(\d+) (\d+) ([a-f0-9]+) ([a-f0-9]+) ([A-Z])(\d+)?\t([^\t]+)(?:\t([^\t]+))?$') + +# Parse output from `git diff-index` +def parse_diff(diff): + m = diff_pat.match(diff) + if not m: + raise ValueError('Failed to parse diff-index line: ' + diff) + return { + 'src_mode': unless_zeroed(m.group(1)), + 'dst_mode': unless_zeroed(m.group(2)), + 'src_hash': unless_zeroed(m.group(3)), + 'dst_hash': unless_zeroed(m.group(4)), + 'status': m.group(5), + 'score': int(m.group(6)) if m.group(6) else None, + 'src_path': m.group(7), + 'dst_path': m.group(8) + } + +zeroed_pat = re.compile(r'^0+$') + +# Returns the argument unless the argument is a string of zeroes, in which case +# returns `None` +def unless_zeroed(s): + return s if not zeroed_pat.match(s) else None + +def get_git_root(): + return subprocess.check_output( + ['git', 'rev-parse', '--show-toplevel'] + ).decode('utf-8').rstrip() + +def normalize_path(p, relative_to=None): + return os.path.abspath( + os.path.join(relative_to, p) if relative_to else p + ) + +def matches_some_path(patterns, target): + is_match = False + for signed_pattern in patterns: + (is_pattern_positive, pattern) = from_signed_pattern(signed_pattern) + if fnmatch(target, normalize_path(pattern)): + is_match = is_pattern_positive + return is_match + +# Checks for a '!' as the first character of a pattern, returns the rest of the +# pattern in a tuple. The tuple takes the form (is_pattern_positive, pattern). +# For example: +# from_signed_pattern('!pat') == (False, 'pat') +# from_signed_pattern('pat') == (True, 'pat') +def from_signed_pattern(pattern): + if pattern[0] == '!': + return (False, pattern[1:]) + else: + return (True, pattern) + +class CustomArgumentParser(argparse.ArgumentParser): + def parse_args(self, args=None, namespace=None): + args, argv = self.parse_known_args(args, namespace) + if argv: + msg = argparse._( + 'unrecognized arguments: %s. Do you need to quote your formatter command?' + ) + self.error(msg % ' '.join(argv)) + return args + +if __name__ == '__main__': + parser = CustomArgumentParser( + description='Transform staged files using a formatting command that accepts content via stdin and produces a result via stdout.', + epilog='Example: %(prog)s --formatter "prettier --stdin-filepath \'{}\'" "src/*.js" "test/*.js"' + ) + parser.add_argument( + '--formatter', '-f', + required=True, + help='Shell command to format files, will run once per file. Occurrences of the placeholder `{}` will be replaced with a path to the file being formatted. (Example: "prettier --stdin-filepath \'{}\'")' + ) + parser.add_argument( + '--no-update-working-tree', + action='store_true', + help='By default formatting changes made to staged file content will also be applied to working tree files via a patch. This option disables that behavior, leaving working tree files untouched.' + ) + parser.add_argument( + '--no-write', + action='store_true', + help='Prevents %(prog)s from modifying staged or working tree files. You can use this option to check staged changes with a linter instead of formatting. With this option stdout from the formatter command is ignored. Example: %(prog)s --no-write -f "eslint --stdin --stdin-filename \'{}\' >&2" "*.js"' + ) + parser.add_argument( + '--version', + action='version', + version='%(prog)s version {}'.format(VERSION), + help='Display version of %(prog)s' + ) + parser.add_argument( + '--verbose', + help='Show the formatting commands that are running', + action='store_true' + ) + parser.add_argument( + 'files', + nargs='+', + help='Patterns that specify files to format. The formatter will only transform staged files that are given here. Patterns may be literal file paths, or globs which will be tested against staged file paths using Python\'s fnmatch function. For example "src/*.js" will match all files with a .js extension in src/ and its subdirectories. Patterns may be negated to exclude files using a "!" character. Patterns are evaluated left-to-right. (Example: "main.js" "src/*.js" "test/*.js" "!test/todo/*")' + ) + args = parser.parse_args() + files = vars(args)['files'] + format_staged_files( + file_patterns=files, + formatter=vars(args)['formatter'], + git_root=get_git_root(), + update_working_tree=not vars(args)['no_update_working_tree'], + write=not vars(args)['no_write'], + verbose=vars(args)['verbose'] + ) diff --git a/Scripts/swiftformat b/Scripts/swiftformat index 3922fbbac..6fb8c822b 100755 --- a/Scripts/swiftformat +++ b/Scripts/swiftformat @@ -2,4 +2,4 @@ ROOT="$(git rev-parse --show-toplevel)" -swift run -c release swiftformat $ROOT +mise x -- swiftformat $ROOT