Skip to content

Commit

Permalink
Merge pull request #97 from omochi/method-chain-style
Browse files Browse the repository at this point in the history
パラメータオブジェクトをメソッドチェーンで構築できるようにする
  • Loading branch information
omochi committed May 5, 2024
2 parents 07a2438 + 2e8f54d commit 19644da
Show file tree
Hide file tree
Showing 26 changed files with 7,331 additions and 403 deletions.
1 change: 1 addition & 0 deletions Codegen/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ DerivedData/
.netrc
.swiftpm
node_modules
data.json
9 changes: 9 additions & 0 deletions Codegen/Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@
"version" : "0.3.0"
}
},
{
"identity" : "swift-collections",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-collections",
"state" : {
"revision" : "94cf62b3ba8d4bed62680a282d4c25f9c63c2efb",
"version" : "1.1.0"
}
},
{
"identity" : "swift-format",
"kind" : "remoteSourceControl",
Expand Down
2 changes: 2 additions & 0 deletions Codegen/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ let package = Package(
)
],
dependencies: [
.package(url: "https://github.com/apple/swift-collections", from: "1.1.0"),
.package(url: "https://github.com/omochi/CodegenKit", from: "1.4.1")
],
targets: [
.target(
name: "SRTCodegen",
dependencies: [
.product(name: "Collections", package: "swift-collections"),
.product(name: "CodegenKit", package: "CodegenKit")
]
),
Expand Down
43 changes: 43 additions & 0 deletions Codegen/Sources/SRTCodegen/Def.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import Collections

struct Def: Codable {
var tagNames: [String]
var voidElements: [String]
var elementAttributes: [String: [String]]
var eventAttributes: [String]
var cssProperties: [String]

mutating func fix() {
tagNames.removeAll { (tagName) in
voidElements.contains(tagName)
}

self.cssProperties = {
var css: OrderedSet<String> = []

for x in cssProperties {
if !x.hasPrefix("-") {
css.remove("-" + x)
}

css.append(x)
}

return css.elements
}()
}

var allAttributes: [String] {
var attrs: OrderedSet<String> = []
attrs.formUnion(elementAttributes["*"] ?? [])

var dict = elementAttributes
dict["*"] = nil

for key in dict.keys.sorted() {
attrs.formUnion(dict[key] ?? [])
}

return attrs.elements
}
}
1 change: 0 additions & 1 deletion Codegen/Sources/SRTCodegen/Keywords.swift

This file was deleted.

29 changes: 29 additions & 0 deletions Codegen/Sources/SRTCodegen/Renderers/AttributesRenderer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Foundation
import CodegenKit

struct AttributesRenderer: Renderer {
var def: Def

func isTarget(file: URL) -> Bool {
file.lastPathComponent == "Attributes.swift"
}

func render(template: inout CodeTemplateModule.CodeTemplate, file: URL, on runner: CodegenKit.CodegenRunner) throws {
let code = def.allAttributes.map { (attribute) in
renderSetter(attribute: attribute)
}.joined(separator: "\n")

template["setters"] = code
}

private func renderSetter(attribute: String) -> String {
let symbol = attribute.kebabToCamel()

return """
public func \(renderIdentifier(symbol))(_ value: String) -> Attributes {
set("\(attribute)", to: value)
}
"""
}
}
32 changes: 32 additions & 0 deletions Codegen/Sources/SRTCodegen/Renderers/EventListenersRenderer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import Foundation
import CodegenKit

struct EventListenersRenderer: Renderer {
var def: Def

func isTarget(file: URL) -> Bool {
file.lastPathComponent == "EventListeners.swift"
}

func render(template: inout CodeTemplateModule.CodeTemplate, file: URL, on runner: CodegenKit.CodegenRunner) throws {
let code = def.eventAttributes.map { (attribute) in
renderSetter(attribute: attribute)
}.joined(separator: "\n")

template["setters"] = code
}

private func renderSetter(attribute: String) -> String {
var attribute = attribute
if attribute.hasPrefix("on") {
attribute.removeFirst(2)
}

return """
public func \(renderIdentifier(attribute))(_ value: EventListener) -> EventListeners {
set("\(attribute)", to: value)
}
"""
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import Foundation
import CodegenKit

struct HTMLTagRenderer: Renderer {
var tags: [String]
var def: Def

func isTarget(file: URL) -> Bool {
file.lastPathComponent == "HTMLTags.swift"
}

func render(template: inout CodeTemplateModule.CodeTemplate, file: URL, on runner: CodegenKit.CodegenRunner) throws {
let code = tags.map { (tag) in
let code = def.tagNames.map { (tag) in
renderTagFunc(tag: tag)
}.joined(separator: "\n")

Expand All @@ -21,28 +21,22 @@ struct HTMLTagRenderer: Renderer {
public func \(renderIdentifier(tag))(
key: AnyHashable? = nil,
ref: RefObject<JSHTMLElement>? = nil,
attributes: Attributes = [:],
listeners: EventListeners = [:],
attributes: Attributes? = nil,
style: Style? = nil,
listeners: EventListeners? = nil,
@ChildrenBuilder _ children: () -> [Node] = { [] }
) -> HTMLElement {
HTMLElement(
tagName: "\(tag)",
key: key,
ref: ref,
attributes: attributes,
style: style,
listeners: listeners,
children: children()
)
}
"""
}

private func renderIdentifier(_ text: String) -> String {
var text = text
if keywords.contains(text) {
text = "`\(text)`"
}
return text
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import Foundation
import CodegenKit

struct HTMLLeafTagRenderer: Renderer {
var tags: [String]
struct HTMLVoidTagRenderer: Renderer {
var def: Def

func isTarget(file: URL) -> Bool {
file.lastPathComponent == "HTMLLeafTags.swift"
file.lastPathComponent == "HTMLVoidTags.swift"
}

func render(template: inout CodeTemplateModule.CodeTemplate, file: URL, on runner: CodegenKit.CodegenRunner) throws {
let code = tags.map { (tag) in
let code = def.voidElements.map { (tag) in
renderTagFunc(tag: tag)
}.joined(separator: "\n")

Expand All @@ -21,14 +21,16 @@ struct HTMLLeafTagRenderer: Renderer {
public func \(tag)(
key: AnyHashable? = nil,
ref: RefObject<JSHTMLElement>? = nil,
attributes: Attributes = [:],
listeners: EventListeners = [:]
attributes: Attributes? = nil,
style: Style? = nil,
listeners: EventListeners? = nil
) -> HTMLElement {
HTMLElement(
tagName: "\(tag)",
key: key,
ref: ref,
attributes: attributes,
style: style,
listeners: listeners
)
}
Expand Down
29 changes: 29 additions & 0 deletions Codegen/Sources/SRTCodegen/Renderers/StyleRenderer.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Foundation
import CodegenKit

struct StyleRenderer: Renderer {
var def: Def

func isTarget(file: URL) -> Bool {
file.lastPathComponent == "Style.swift"
}

func render(template: inout CodeTemplateModule.CodeTemplate, file: URL, on runner: CodegenKit.CodegenRunner) throws {
let code = def.cssProperties.map { (attribute) in
renderSetter(attribute: attribute)
}.joined(separator: "\n")

template["setters"] = code
}

private func renderSetter(attribute: String) -> String {
let symbol = attribute.kebabToCamel()

return """
public func \(renderIdentifier(symbol))(_ value: String) -> Style {
set("\(attribute)", to: value)
}
"""
}
}
18 changes: 9 additions & 9 deletions Codegen/Sources/SRTCodegen/SRTCodegen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,25 @@ public struct SRTCodegen {
self.codegenDir = URL(filePath: ".", directoryHint: .isDirectory)
self.swiftReactDir = codegenDir.deletingLastPathComponent()
self.htmlSourceDir = swiftReactDir.appending(components: "Sources", "React", "HTML", directoryHint: .isDirectory)
let tagsDir = codegenDir.appending(components: "node_modules", "html-tags")
let tagsJSON = try Data(contentsOf: tagsDir.appending(path: "html-tags.json"))
let json = try Data(contentsOf: codegenDir.appending(path: "data.json"))
let decoder = JSONDecoder()
self.tags = try decoder.decode(Array<String>.self, from: tagsJSON)
let leafJSON = try Data(contentsOf: tagsDir.appending(path: "html-tags-void.json"))
self.leafTags = try decoder.decode(Array<String>.self, from: leafJSON)
self.def = try decoder.decode(Def.self, from: json)
def.fix()
}

var codegenDir: URL
var swiftReactDir: URL
var htmlSourceDir: URL
var tags: [String]
var leafTags: [String]
var def: Def

public func run() throws {
let runner = CodegenRunner(
renderers: [
HTMLTagRenderer(tags: tags),
HTMLLeafTagRenderer(tags: leafTags)
HTMLTagRenderer(def: def),
HTMLVoidTagRenderer(def: def),
AttributesRenderer(def: def),
StyleRenderer(def: def),
EventListenersRenderer(def: def)
]
)

Expand Down
38 changes: 38 additions & 0 deletions Codegen/Sources/SRTCodegen/Utils.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Foundation

public let keywords = [
"as",
"class",
"continue",
"default",
"defer",
"for",
"is",
"var",
]

func renderIdentifier(_ text: String) -> String {
var text = text
if keywords.contains(text) {
text = "`\(text)`"
}
return text
}

extension String {
func kebabToCamel() -> String {
let strs = self.components(separatedBy: "-")
.filter { !$0.isEmpty }

var result = ""
for (index, str) in strs.enumerated() {
if index == 0 {
result += str.lowercased()
} else {
result += str.capitalized
}
}

return result
}
}
20 changes: 16 additions & 4 deletions Codegen/index.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
import htmlTags from "html-tags/index.js";
import htmlLeafTags from "html-tags/void.js";
import { htmlTagNames } from "html-tag-names";
import { htmlVoidElements } from "html-void-elements";
import { htmlElementAttributes } from "html-element-attributes";
import { htmlEventAttributes } from "html-event-attributes";
import * as kcpModule from "known-css-properties";

console.log(htmlTags);
console.log(htmlLeafTags);
const json = {
"tagNames": htmlTagNames,
"voidElements": htmlVoidElements,
"elementAttributes": htmlElementAttributes,
"eventAttributes": htmlEventAttributes,
"cssProperties": kcpModule.all
};

const string = JSON.stringify(json, undefined, 2);

console.log(string);
Loading

0 comments on commit 19644da

Please sign in to comment.