Skip to content

Commit

Permalink
Appkit support (#22)
Browse files Browse the repository at this point in the history
* Add `frameworks` key

* Added AppKit support

* Lint

* Cleanup

* Lint

* Update YAML template

* Update template

* Refactor color indentation

* Cleanup

* Update README

* Update CHANGELOG

* Version bump

* Split template

* Fix AppKit + SwiftUI combination

* Add template tests

* Make typealias private

* Update fixtures

* HEREDOC -> SWIFT
  • Loading branch information
raymondjavaxx authored Jul 28, 2023
1 parent 768dc70 commit 5127586
Show file tree
Hide file tree
Showing 28 changed files with 1,243 additions and 224 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Changelog
All notable changes to this project will be documented in this file.

## vNEXT
## v0.7.0
### Added
- Added AppKit support.
### Changed
- Stylegen now requires Ruby 2.7 or higher.

Expand Down
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
stylegen (0.6.1)
stylegen (0.7.0)
dry-cli (~> 1.0.0)
dry-inflector (~> 1.0.0)
json_schemer (~> 1.0.3)
Expand Down
16 changes: 7 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# stylegen

A CLI utility that allows managing the colors used in an iOS app from a centralized YAML file in a type-safe way.
A CLI utility for managing the colors used in an iOS/macOS app from a centralized YAML file in a type-safe way.

![CI](https://github.com/raymondjavaxx/stylegen/workflows/CI/badge.svg?branch=master)

Expand Down Expand Up @@ -38,7 +38,12 @@ The generated YAML file will look similar to this:
# Path of generated Swift file.
output_path: "Colors.swift"

# Enables SwiftUI support
# UI frameworks to support.
# frameworks:
# - UIKit
# - AppKit

# Enables SwiftUI support.
# swiftui: false

# Key-value pairs of theme colors.
Expand Down Expand Up @@ -100,10 +105,3 @@ self.backgroundColor = .theme(.accent)

The `.theme()` static method serves as a namespace to easily distinguish between UIKit's built-in colors and our custom
colors. The name of the namespacing function gets inferred from the `system_name` property in the YAML file.

## TODO

* ~~`$ stylegen init` command~~
* Option to specify target frameworks: AppKit, UIKit, Core Graphics, and SwiftUI
* ~~SwiftUI support~~
* AppKit support
7 changes: 6 additions & 1 deletion lib/stylegen/cli/template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@
# Path of generated Swift file.
output_path: "Colors.swift"

# Enables SwiftUI support
# UI frameworks to support.
# frameworks:
# - UIKit
# - AppKit

# Enables SwiftUI support.
# swiftui: false

# Key-value pairs of theme colors.
Expand Down
19 changes: 10 additions & 9 deletions lib/stylegen/colors/base_elevated_color.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require 'stylegen/indent'

module Stylegen
class BaseElevatedColor
attr_reader :description
Expand All @@ -10,15 +12,14 @@ def initialize(base, elevated)
end

def to_s(struct_name, indent = 0)
indent_prefix = ' ' * indent

result = []
result << "#{struct_name}("
result << "#{indent_prefix} base: #{@base.to_s(struct_name, indent + 4)},"
result << "#{indent_prefix} elevated: #{@elevated.to_s(struct_name, indent + 4)}"
result << "#{indent_prefix})"

result.join("\n")
Indent.with_level(indent) do
<<~SWIFT.chomp
#{struct_name}(
base: #{@base.to_s(struct_name, 4).lstrip},
elevated: #{@elevated.to_s(struct_name, 4).lstrip}
)
SWIFT
end
end
end
end
29 changes: 15 additions & 14 deletions lib/stylegen/colors/color.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require 'stylegen/indent'

module Stylegen
class Color
attr_reader :red, :green, :blue, :alpha
Expand Down Expand Up @@ -41,20 +43,19 @@ def grayscale?
end

def to_s(struct_name, indent = 0)
if grayscale?
"#{struct_name}(white: #{@red}, alpha: #{@alpha})"
else
indent_prefix = ' ' * indent

result = []
result << "#{struct_name}("
result << "#{indent_prefix} red: #{@red},"
result << "#{indent_prefix} green: #{@green},"
result << "#{indent_prefix} blue: #{@blue},"
result << "#{indent_prefix} alpha: #{@alpha}"
result << "#{indent_prefix})"

result.join("\n")
Indent.with_level(indent) do
if grayscale?
"#{struct_name}(white: #{@red}, alpha: #{@alpha})"
else
<<~SWIFT.chomp
#{struct_name}(
red: #{@red},
green: #{@green},
blue: #{@blue},
alpha: #{@alpha}
)
SWIFT
end
end
end
end
Expand Down
19 changes: 10 additions & 9 deletions lib/stylegen/colors/light_dark_color.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require 'stylegen/indent'

module Stylegen
class LightDarkColor
def initialize(light, dark)
Expand All @@ -8,15 +10,14 @@ def initialize(light, dark)
end

def to_s(struct_name, indent = 0)
indent_prefix = ' ' * indent

result = []
result << "#{struct_name}("
result << "#{indent_prefix} light: #{@light.to_s(struct_name, indent + 4)},"
result << "#{indent_prefix} dark: #{@dark.to_s(struct_name, indent + 4)}"
result << "#{indent_prefix})"

result.join("\n")
Indent.with_level(indent) do
<<~SWIFT.chomp
#{struct_name}(
light: #{@light.to_s(struct_name, 4).lstrip},
dark: #{@dark.to_s(struct_name, 4).strip}
)
SWIFT
end
end
end
end
35 changes: 18 additions & 17 deletions lib/stylegen/data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,8 @@ def inflector
@inflector ||= Dry::Inflector.new
end

def file_header
header = @data['header'] || <<~HEADER
//
// {{STYLEGEN_FILENAME}}
//
// Autogenerated by stylegen ({{STYLEGEN_VERSION}})
// DO NOT EDIT
//
HEADER

replacements = {
'STYLEGEN_FILENAME' => basename,
'STYLEGEN_VERSION' => version,
'STYLEGEN_YEAR' => Date.today.year
}

header.strip.gsub(/{{(\w+)}}/) { replacements[Regexp.last_match(1)] || '' }
def custom_header
@data['header']
end

def version
Expand All @@ -49,6 +34,22 @@ def output_path
@data['output_path']
end

def frameworks
@data['frameworks'] || ['UIKit']
end

def supports_uikit?
frameworks.include?('UIKit')
end

def supports_appkit?
frameworks.include?('AppKit')
end

def multiplatform?
supports_uikit? && supports_appkit?
end

def swiftui?
@data['swiftui'] || false
end
Expand Down
32 changes: 32 additions & 0 deletions lib/stylegen/indent.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

module Stylegen
class Indent
def initialize(level, string = nil)
@level = level
@data = []
@data << string unless string.nil?
end

def <<(string)
@data << string
end

def to_s
result = @data.join.lines.map do |line|
if line.strip.empty?
line
else
"#{' ' * @level}#{line}"
end
end
result.join
end

def self.with_level(level)
indent = Indent.new(level)
indent << yield
indent.to_s
end
end
end
35 changes: 35 additions & 0 deletions lib/stylegen/partials/colors.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

module Stylegen
module Partials
class Colors
attr_reader :data

def initialize(data)
@data = data
end

def to_s
result = []
result << '// MARK: Colors'
result << ''
result << "#{data.effective_access_level} extension #{data.struct_name} {".lstrip

data.color_entries.each do |entry|
unless entry[:description].nil?
entry[:description].strip.lines.each do |line|
result << " /// #{line.strip}"
end
end

result << " static let #{entry[:property]} = #{entry[:color].to_s(data.struct_name, 4).lstrip}"
result << '' unless entry == data.color_entries.last
end

result << '}'
result << ''
result.join("\n")
end
end
end
end
36 changes: 36 additions & 0 deletions lib/stylegen/partials/file_header.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

module Stylegen
module Partials
class FileHeader
attr_reader :data

def initialize(data)
@data = data
end

def to_s
replacements = {
'STYLEGEN_FILENAME' => data.basename,
'STYLEGEN_VERSION' => data.version,
'STYLEGEN_YEAR' => Date.today.year
}

"#{header_template}\n".gsub(/{{(\w+)}}/) { replacements[Regexp.last_match(1)] || '' }
end

private

def header_template
data.custom_header&.strip || <<~HEADER.chomp
//
// {{STYLEGEN_FILENAME}}
//
// Autogenerated by stylegen ({{STYLEGEN_VERSION}})
// DO NOT EDIT
//
HEADER
end
end
end
end
33 changes: 33 additions & 0 deletions lib/stylegen/partials/imports.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# frozen_string_literal: true

module Stylegen
module Partials
class Imports
attr_reader :data

def initialize(data)
@data = data
end

def to_s
result = []

if data.multiplatform?
result << '#if canImport(UIKit)'
result << 'import UIKit'
result << '#elseif canImport(AppKit)'
result << 'import AppKit'
result << '#endif'
elsif data.supports_uikit?
result << 'import UIKit'
elsif data.supports_appkit?
result << 'import AppKit'
end

result << 'import SwiftUI' if data.swiftui?
result << ''
result.join("\n")
end
end
end
end
Loading

0 comments on commit 5127586

Please sign in to comment.