diff --git a/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..919434a
--- /dev/null
+++ b/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/.swiftpm/xcode/package.xcworkspace/xcuserdata/ivanmikhailovskii.xcuserdatad/UserInterfaceState.xcuserstate b/.swiftpm/xcode/package.xcworkspace/xcuserdata/ivanmikhailovskii.xcuserdatad/UserInterfaceState.xcuserstate
new file mode 100644
index 0000000..fff09f3
Binary files /dev/null and b/.swiftpm/xcode/package.xcworkspace/xcuserdata/ivanmikhailovskii.xcuserdatad/UserInterfaceState.xcuserstate differ
diff --git a/.swiftpm/xcode/xcuserdata/ivanmikhailovskii.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/.swiftpm/xcode/xcuserdata/ivanmikhailovskii.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
new file mode 100644
index 0000000..cbadbdc
--- /dev/null
+++ b/.swiftpm/xcode/xcuserdata/ivanmikhailovskii.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
@@ -0,0 +1,6 @@
+
+
+
diff --git a/.swiftpm/xcode/xcuserdata/ivanmikhailovskii.xcuserdatad/xcschemes/xcschememanagement.plist b/.swiftpm/xcode/xcuserdata/ivanmikhailovskii.xcuserdatad/xcschemes/xcschememanagement.plist
new file mode 100644
index 0000000..505af2a
--- /dev/null
+++ b/.swiftpm/xcode/xcuserdata/ivanmikhailovskii.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -0,0 +1,27 @@
+
+
+
+
+ SchemeUserState
+
+ SQAssetsValidator.xcscheme_^#shared#^_
+
+ orderHint
+ 0
+
+ Spectre (Playground).xcscheme
+
+ orderHint
+ 1
+
+
+ SuppressBuildableAutocreation
+
+ SQAssetsValidatort
+
+ primary
+
+
+
+
+
diff --git a/Package.resolved b/Package.resolved
new file mode 100644
index 0000000..c9bbd1f
--- /dev/null
+++ b/Package.resolved
@@ -0,0 +1,61 @@
+{
+ "object": {
+ "pins": [
+ {
+ "package": "PathKit",
+ "repositoryURL": "https://github.com/kylef/PathKit.git",
+ "state": {
+ "branch": null,
+ "revision": "3bfd2737b700b9a36565a8c94f4ad2b050a5e574",
+ "version": "1.0.1"
+ }
+ },
+ {
+ "package": "Spectre",
+ "repositoryURL": "https://github.com/kylef/Spectre.git",
+ "state": {
+ "branch": null,
+ "revision": "26cc5e9ae0947092c7139ef7ba612e34646086c7",
+ "version": "0.10.1"
+ }
+ },
+ {
+ "package": "Stencil",
+ "repositoryURL": "https://github.com/stencilproject/Stencil.git",
+ "state": {
+ "branch": null,
+ "revision": "4f222ac85d673f35df29962fc4c36ccfdaf9da5b",
+ "version": "0.15.1"
+ }
+ },
+ {
+ "package": "swift-argument-parser",
+ "repositoryURL": "https://github.com/apple/swift-argument-parser",
+ "state": {
+ "branch": null,
+ "revision": "6b2aa2748a7881eebb9f84fb10c01293e15b52ca",
+ "version": "0.5.0"
+ }
+ },
+ {
+ "package": "swift-log",
+ "repositoryURL": "https://github.com/apple/swift-log.git",
+ "state": {
+ "branch": null,
+ "revision": "3d8596ed08bd13520157f0355e35caed215ffbfa",
+ "version": "1.6.3"
+ }
+ },
+ {
+ "package": "Yams",
+ "repositoryURL": "https://github.com/jpsim/Yams.git",
+ "state": {
+ "branch": null,
+ "revision": "9ff1cc9327586db4e0c8f46f064b6a82ec1566fa",
+ "version": "4.0.6"
+ }
+ }
+ ]
+ },
+ "version": 1
+}
diff --git a/Package.swift b/Package.swift
new file mode 100644
index 0000000..6ca9287
--- /dev/null
+++ b/Package.swift
@@ -0,0 +1,39 @@
+// swift-tools-version:5.7
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "SQAssetsValidator",
+ platforms: [
+ .macOS(.v13),
+ ],
+ products: [
+ .executable(name: "SQAssetsValidatort", targets: ["SQAssetsValidator"])
+ ],
+ dependencies: [
+ .package(url: "https://github.com/apple/swift-argument-parser", from: "0.3.0"),
+ .package(url: "https://github.com/jpsim/Yams.git", from: "4.0.0"),
+ .package(url: "https://github.com/apple/swift-log.git", from: "1.4.0"),
+ .package(url: "https://github.com/stencilproject/Stencil.git", from: "0.14.0"),
+ ],
+ targets: [
+ // Main target
+ .target(
+ name: "SQAssetsValidator",
+ dependencies: [
+ "Utils",
+ .product(name: "ArgumentParser", package: "swift-argument-parser"),
+ .product(name: "Yams", package: "Yams"),
+ .product(name: "Logging", package: "swift-log")
+ ],
+ path: "./Sources/AssetsValidator"
+ ),
+
+ // Shared target
+ .target(
+ name: "Utils",
+ path: "./Sources/Utils"
+ ),
+ ]
+)
diff --git a/README.md b/README.md
index 6977727..4351fe6 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,24 @@
# SQAssetsValidator
+
+validator-config.yaml
+
+```
+icon:
+ graphicsFilePath: ./SQCoreGraphics.swift
+ iconPath: ./Resources/Assets/Assets.xcassets/Icons
+ illustrationsPath: ./Resources/Assets/Assets.xcassets/Illustrations
+ ignore:
+ - imgHeaderLogo
+ - imgSplashLogoSmall
+ - icNotification
+ - icNotificationMini
+palette:
+ folderFilePath: ./Palette
+ colorPath: ./Resources/Assets/Colors.xcassets/Colors
+typography:
+ resourcesJSON: ./Resources/Core/core_typography.json
+ folderFilesPath: ./Styles
+dimension:
+ resourcesJSON: ./Resources/Core/core_dimensions.json
+ dimensionsFilePath: ./SQCoreDimensions.swift
+```
diff --git a/Sources/AssetsValidator/Input/Params.swift b/Sources/AssetsValidator/Input/Params.swift
new file mode 100644
index 0000000..c2dc163
--- /dev/null
+++ b/Sources/AssetsValidator/Input/Params.swift
@@ -0,0 +1,40 @@
+//
+// Params.swift
+// SQAssetsValidator
+//
+// Created by Ivan Mikhailovskii on 22.07.2025.
+//
+
+struct Params: Decodable {
+
+ struct Palette: Decodable {
+ let folderFilePath: String
+ let ignore: [String]?
+ let colorPath: String
+ }
+
+ struct Icon: Decodable {
+ let graphicsFilePath: String
+ let iconPath: String
+ let illustrationsPath: String
+ let ignore: [String]?
+ }
+
+ struct Typography: Decodable {
+ let folderFilesPath: String
+ let resourcesJSON: String
+ let ignore: [String]?
+ }
+
+ struct Dimension: Decodable {
+ let dimensionsFilePath: String
+ let resourcesJSON: String
+ let ignore: [String]?
+ }
+
+ let sqCorePath: String?
+ let icon: Icon?
+ let palette: Palette?
+ let typography: Typography?
+ let dimension: Dimension?
+}
diff --git a/Sources/AssetsValidator/Input/ParamsReader.swift b/Sources/AssetsValidator/Input/ParamsReader.swift
new file mode 100644
index 0000000..8362899
--- /dev/null
+++ b/Sources/AssetsValidator/Input/ParamsReader.swift
@@ -0,0 +1,36 @@
+//
+// ParceParams.swift
+// SQAssetsValidator
+//
+// Created by Ivan Mikhailovskii on 22.07.2025.
+//
+
+import Foundation
+import Yams
+
+final class ParamsReader {
+
+ private let fileManager: FileManager
+ private let inputPath: String
+
+ init(
+ inputPath: String = "./validator-config.yaml",
+ fileManager: FileManager = .default
+ ) {
+ self.inputPath = inputPath
+ self.fileManager = fileManager
+ }
+
+ func read() throws -> Params {
+ return try readParams(filePath: inputPath)
+ }
+
+ private func readParams(
+ filePath: String
+ ) throws -> Params {
+ let data = try Data(contentsOf: URL(fileURLWithPath: filePath))
+
+ let decoder = YAMLDecoder()
+ return try decoder.decode(Params.self, from: String(data: data, encoding: .utf8)!)
+ }
+}
diff --git a/Sources/AssetsValidator/Subcommands/DimensionsValidator.swift b/Sources/AssetsValidator/Subcommands/DimensionsValidator.swift
new file mode 100644
index 0000000..ef110d4
--- /dev/null
+++ b/Sources/AssetsValidator/Subcommands/DimensionsValidator.swift
@@ -0,0 +1,62 @@
+//
+// DimensionsValidator.swift
+// SQAssetsValidator
+//
+// Created by Ivan Mikhailovskii on 22.07.2025.
+//
+
+import Foundation
+import ArgumentParser
+import Logging
+import Utils
+
+extension SQAssetsValidatorCommand {
+
+ struct DimensionsValidator: ParsableCommand {
+
+ static let configuration = CommandConfiguration(
+ commandName: "dimensions",
+ abstract: "Validate dimensions from project",
+ discussion: "Validate dimensions from project"
+ )
+
+ func run() throws {
+ let logger = Logger(label: "assets-validator")
+ let params = try ParamsReader().read()
+
+ let url = URL(fileURLWithPath: params.dimension?.resourcesJSON ?? "")
+ let dictonary = try? UtilsJson.loadJSON(from: url)
+
+ var named = [String]()
+
+ dictonary?.keys.forEach {
+ named.append($0)
+ }
+
+ let urlDimensions = URL(fileURLWithPath: params.dimension?.dimensionsFilePath ?? "")
+
+ guard let data = try? Data(contentsOf: urlDimensions)
+ else { fatalError() }
+
+ let fileContent = String(decoding: data, as: UTF8.self)
+
+ var notFoundResources = ""
+ named.forEach { name in
+ if params.dimension?.ignore?.contains(name) ?? false {
+ return
+ }
+
+ if !fileContent.contains(name) {
+ notFoundResources.append("not found: \(name)\n")
+ }
+ }
+
+ if notFoundResources.isEmpty {
+ logger.info("Dimensions resources validate")
+ } else {
+ logger.error(Logger.Message(stringLiteral: notFoundResources))
+ fatalError()
+ }
+ }
+ }
+}
diff --git a/Sources/AssetsValidator/Subcommands/IconValidator.swift b/Sources/AssetsValidator/Subcommands/IconValidator.swift
new file mode 100644
index 0000000..712548b
--- /dev/null
+++ b/Sources/AssetsValidator/Subcommands/IconValidator.swift
@@ -0,0 +1,79 @@
+//
+// IconValidator.swift
+// SQAssetsValidator
+//
+// Created by Ivan Mikhailovskii on 21.07.2025.
+//
+
+import Foundation
+import ArgumentParser
+import Logging
+
+extension SQAssetsValidatorCommand {
+
+ struct IconValidator: ParsableCommand {
+
+ static let configuration = CommandConfiguration(
+ commandName: "icons",
+ abstract: "Validate icons from project",
+ discussion: "Validate icons from project"
+ )
+
+ func run() throws {
+ let logger = Logger(label: "assets-validator")
+ let params = try ParamsReader().read()
+
+ let url = URL(fileURLWithPath: "\(params.icon?.graphicsFilePath ?? "")")
+ guard let data = try? Data(contentsOf: url)
+ else { return }
+
+ let fileContent = String(decoding: data, as: UTF8.self)
+
+ let namedRanges = fileContent.ranges(of: #/\s+named:\s+"(\w+)",/#)
+
+ var named = [String]()
+ namedRanges.forEach { range in
+ let rawNamedEntry = String(fileContent[fileContent.index(after: range.lowerBound).. [String: Any] {
+ let data = try? Data(contentsOf: url)
+
+ guard let data,
+ let json = try? JSONSerialization.jsonObject(with: data, options: []),
+ let dictionary = json as? [String: Any] else {
+
+ throw JSONError.parsingFailed
+ }
+
+ return dictionary
+ }
+}