Skip to content

Commit e1afb3f

Browse files
committed
first commit
1 parent cc2c251 commit e1afb3f

File tree

108 files changed

+4997
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+4997
-0
lines changed

.github/FUNDING.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# These are supported funding model platforms
2+
3+
buy_me_a_coffee: zhgchgli

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
xcuserdata/
5+
DerivedData/
6+
.swiftpm/configuration/registries.json
7+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
8+
.netrc

Configuration.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Paths to ignore when scanning for source files
2+
ignorePaths:
3+
- "Pods"
4+
- "Frameworks"
5+
- "Products"
6+
7+
# Allowed file types to include when scanning
8+
allowFileTypes:
9+
- "sourcecode.swift" # Swift source code files
10+
- "sourcecode.c.objc" # Objective-C source code files
11+
- "sourcecode.cpp.objcpp" # Objective-C++ source code files
12+
- "sourcecode.c.h" # C/Objective-C header files
13+
- "file.xib" # Interface Builder XIB files
14+
- "file.storyboard" # Interface Builder Storyboard files
15+
- "folder.assetcatalog" # Asset catalog containing images and resources
16+
- "text.json.xcstrings" # Localized strings in JSON format
17+
- "text.plist.strings" # Localized strings in plist format
18+
19+
# Whether to move files only, without changing .xcodeproj settings
20+
moveFileOnly: false

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 ZRealm
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Package.resolved

Lines changed: 60 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// swift-tools-version: 5.10
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "XCFolder",
8+
platforms: [
9+
.macOS(.v13)
10+
],
11+
dependencies: [
12+
.package(url: "https://github.com/tuist/XcodeProj.git", .upToNextMajor(from: "8.12.0")),
13+
.package(url: "https://github.com/apple/swift-argument-parser.git", .upToNextMajor(from: "1.2.0")),
14+
.package(url: "https://github.com/jpsim/Yams.git", .upToNextMajor(from: "5.3.1"))
15+
],
16+
targets: [
17+
// Targets are the basic building blocks of a package, defining a module or a test suite.
18+
// Targets can depend on other targets in this package and products from dependencies.
19+
.executableTarget(
20+
name: "XCFolder",
21+
dependencies: [
22+
.product(name: "XcodeProj", package: "XcodeProj"),
23+
.product(name: "ArgumentParser", package: "swift-argument-parser"),
24+
.product(name: "Yams", package: "Yams")
25+
],
26+
resources: [
27+
]
28+
),
29+
]
30+
)

README.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# XCFolder
2+
3+
<p align="center">
4+
<img width="700" alt="image" src="https://github.com/user-attachments/assets/82da28b2-5161-4379-90f0-4ba331f76b88" />
5+
</p>
6+
7+
XCFolder is a powerful utility that converts Xcode virtual folders (group) into real filesystem directories (folder), facilitating seamless migration to modern build systems like Tuist or XcodeGen.
8+
9+
This tool ensures perfect synchronization between your Xcode project structure and the actual filesystem organization, making project maintenance more intuitive and efficient.
10+
11+
## Key Features
12+
- **Smart Group Conversion**: Intelligently transforms Xcode virtual groups into physical directories while preserving project structure
13+
- **Perfect Synchronization**: Maintains 1:1 mapping between Xcode project navigator and filesystem directories
14+
- **Automated Organization**: Eliminates manual folder management with automated synchronization
15+
- **Migration Ready**: Prepares your project structure for modern build systems like Tuist and XcodeGen
16+
17+
## Usage
18+
### Step 1. Clone this repo
19+
```
20+
git clone https://github.com/ZhgChgLi/XCFolder.git
21+
```
22+
23+
#### Modify Configuration.yml if needed
24+
`./Configuration.yaml`:
25+
26+
```yaml
27+
# Paths to ignore when scanning for source files
28+
ignorePaths:
29+
- "Pods"
30+
- "Frameworks"
31+
- "Products"
32+
33+
# Allowed file types to include when scanning
34+
allowFileTypes:
35+
- "sourcecode.swift" # Swift source code files
36+
- "sourcecode.c.objc" # Objective-C source code files
37+
- "sourcecode.cpp.objcpp" # Objective-C++ source code files
38+
- "sourcecode.c.h" # C/Objective-C header files
39+
- "file.xib" # Interface Builder XIB files
40+
- "file.storyboard" # Interface Builder Storyboard files
41+
- "folder.assetcatalog" # Asset catalog containing images and resources
42+
- "text.json.xcstrings" # Localized strings in JSON format
43+
- "text.plist.strings" # Localized strings in plist format
44+
45+
# Whether to move files only, without changing .xcodeproj settings
46+
moveFileOnly: false
47+
48+
```
49+
50+
### Step 2. Run with Swift
51+
```
52+
cd ./XCFolder
53+
swift run XCFolder YOUR_XCODEPROJ_FILE.xcodeproj ./Configuration.yaml
54+
```
55+
#### For example
56+
```
57+
swift run XCFolder ./TestProject/DCDeviceTest.xcodeproj ./Configuration.yaml
58+
```
59+
60+
### Step 3. Wait for the execution to complete.
61+
<img width="700" alt="image" src="https://github.com/user-attachments/assets/778c6edc-28df-465c-9c96-7fa866943cc1" />
62+
63+
64+
### Step 4: Done, Have a great day! 🚀🚀🚀
65+
<img width="700" alt="image" src="https://github.com/user-attachments/assets/615acad8-647e-41f5-aee6-ebf7280d30c5" />
66+
67+
## Technical Details
68+
The entire project is written in Swift and runs as an SPM command-line tool.
69+
70+
You can modify the source code by opening `Package.swift` if needed.
71+
72+
## Inspiration & Dependencies
73+
- [synx](https://github.com/venmo/synx)
74+
- [xcodeproj](https://github.com/tuist/xcodeproj)
75+
- [Yams](https://github.com/jpsim/Yams)
76+
77+
## About
78+
- [ZhgChg.Li](https://zhgchg.li/)
79+
- [ZhgChgLi's Medium](https://blog.zhgchg.li/)
80+
81+
## Other works
82+
### Swift Libraries
83+
- [ZMarkupParser](https://github.com/ZhgChgLi/ZMarkupParser) is a pure-Swift library that helps you to convert HTML strings to NSAttributedString with customized style and tags.
84+
- [ZPlayerCacher](https://github.com/ZhgChgLi/ZPlayerCacher) is a lightweight implementation of the AVAssetResourceLoaderDelegate protocol that enables AVPlayerItem to support caching streaming files.
85+
- [ZNSTextAttachment](https://github.com/ZhgChgLi/ZNSTextAttachment) enables NSTextAttachment to download images from remote URLs, support both UITextView and UILabel.
86+
87+
### Integration Tools
88+
- [ZReviewTender](https://github.com/ZhgChgLi/ZReviewTender) is a tool for fetching app reviews from the App Store and Google Play Console and integrating them into your workflow.
89+
- [ZMediumToMarkdown](https://github.com/ZhgChgLi/ZMediumToMarkdown) is a powerful tool that allows you to effortlessly download and convert your Medium posts to Markdown format.
90+
- [linkyee](https://github.com/ZhgChgLi/linkyee) is a fully customized, open-source LinkTree alternative deployed directly on GitHub Pages.
91+
92+
93+
94+
# Donate
95+
96+
[![Buy Me A Coffe](https://img.buymeacoffee.com/button-api/?text=Buy%20me%20a%20beer!&emoji=%F0%9F%8D%BA&slug=zhgchgli&button_colour=FFDD00&font_colour=000000&font_family=Bree&outline_colour=000000&coffee_colour=ffffff)](https://www.buymeacoffee.com/zhgchgli)
97+
98+
If you find this library helpful, please consider starring the repo or recommending it to your friends.
99+
100+
Feel free to open an issue or submit a fix/contribution via pull request. :)

Sources/Model/Configuration.swift

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//
2+
// Configuration.swift
3+
// XCFolder
4+
//
5+
// Created by zhgchgli on 2025/3/1.
6+
//
7+
8+
import PathKit
9+
10+
struct Configuration: CustomStringConvertible {
11+
/// Paths to ignore when scanning for source files
12+
let ignorePaths: [Path]
13+
/// Allowed file types to include when scanning
14+
let allowFileTypes: [String]
15+
/// Whether to move files only, without changing .xcodeproj settings
16+
let moveFileOnly: Bool
17+
18+
var description: String {
19+
return """
20+
# Ignore Paths: \(ignorePaths)
21+
# Allow File Types: \(allowFileTypes)
22+
# Move File Only: \(moveFileOnly)
23+
"""
24+
}
25+
26+
init() {
27+
self.ignorePaths = ["Pods", "Frameworks", "Products"]
28+
self.allowFileTypes = ["sourcecode.swift", "sourcecode.c.objc", "sourcecode.cpp.objcpp", "sourcecode.c.h","file.xib","file.storyboard","folder.assetcatalog","text.json.xcstrings","text.plist.strings"]
29+
self.moveFileOnly = false
30+
}
31+
32+
init(ignorePaths: [Path], allowFileTypes: [String], moveFileOnly: Bool) {
33+
self.ignorePaths = ignorePaths
34+
self.allowFileTypes = allowFileTypes
35+
self.moveFileOnly = moveFileOnly
36+
}
37+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//
2+
// ConfigurationEntity.swift
3+
// XCFolder
4+
//
5+
// Created by zhgchgli on 2025/3/1.
6+
//
7+
8+
import Foundation
9+
import Yams
10+
11+
struct ConfigurationEntity: Decodable {
12+
/// Paths to ignore when scanning for source files
13+
let ignorePaths: [String]
14+
/// Allowed file types to include when scanning
15+
let allowFileTypes: [String]
16+
/// Whether to move files only, without changing .xcodeproj settings
17+
let moveFileOnly: Bool
18+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// ConfigurationMapper.swift
3+
// XCFolder
4+
//
5+
// Created by zhgchgli on 2025/3/1.
6+
//
7+
8+
import Foundation
9+
import PathKit
10+
11+
struct ConfigurationMapper {
12+
static func map(from entity: ConfigurationEntity) -> Configuration {
13+
let ignorePaths = entity.ignorePaths.map { Path($0) }.map ({ path in
14+
if path.string.hasPrefix("/") {
15+
return Path(String(path.string.dropFirst()))
16+
} else {
17+
return path
18+
}
19+
})
20+
let allowFileTypes = entity.allowFileTypes
21+
let moveFileOnly = entity.moveFileOnly
22+
return Configuration(ignorePaths: ignorePaths, allowFileTypes: allowFileTypes, moveFileOnly: moveFileOnly)
23+
}
24+
}

0 commit comments

Comments
 (0)