Skip to content

パラメータオブジェクトをメソッドチェーンで構築できるようにする #97

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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