Skip to content

Commit

Permalink
Upgrade the package (#122)
Browse files Browse the repository at this point in the history
* Add the namespace attribute for the vector element

* Add tests for the vector attributes

* Revise some of the vector attributes

* Revise the converter

* Remove the toggle component

* Revise the link component

* Revise and improve the css

It's better to use logical properties for control the layout. Also, a different color scheme depending on the users default appearance.

* Add a custom select

* Add the points attribute for the vector elements polygon and polyline

* Add a custom datepicker

* Add the javascript for the dropdown

* Add the slot element for web component technology

* Add the shadow root mode attribute for the template element

* Add a css minifier

* Add a javascript minifier

* Revise the css minifier and add it as an internal target

As a target it becomes testable.

* Combine the tokenizer all together into one minifier

* Add some minification tests and also revise the minifier

* Revise the javascript tokenizer and minifier

* Revise the stylesheet tokenizer and minifier

* Revise the minifier and clean up the stylesheets and javascript files

* Add the minifier to the deploy command

* Fix some grammar for the javascript tokenizer

* Change the dark mode behaviour

* Fix the tokenizing of an attribute selector

* Fix the tokenizing of a comma character

* Add css resets

* Rework all of the css

* Fix failing tests

* Fix the minification of arguments in a css function

* Fix the minification of a css selector on top layer

* Fix the minification of a string value

* Fix the minification of a selector

* Separate the javascript for the interactions

The javascript for the interactions needs to be declared in an other way, therefore it should be its own file, when it gets bundled.

* Improve the property and selector distinction

* Revise some components css and js
  • Loading branch information
mattesmohr authored Jun 16, 2023
1 parent b160413 commit e919e51
Show file tree
Hide file tree
Showing 89 changed files with 7,649 additions and 2,287 deletions.
13 changes: 12 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ let package = Package(
.product(name: "Vapor", package: "vapor"),
]
),
.target(
name: "Minifier",
path: "Sources/Utilities"
),
.testTarget(
name: "HTMLKitTests",
dependencies: [
Expand Down Expand Up @@ -92,6 +96,12 @@ let package = Package(
.copy("Localization")
]
),
.testTarget(
name: "UtilitiesTests",
dependencies: [
.target(name: "Minifier"),
]
),
.executableTarget(
name: "ConvertCommand",
dependencies: [
Expand All @@ -102,7 +112,8 @@ let package = Package(
.executableTarget(
name: "DeployCommand",
dependencies: [
.target(name: "HTMLKitComponents")
.target(name: "HTMLKitComponents"),
.target(name: "Minifier")
],
path: "Sources/Commands/Components"
),
Expand Down
84 changes: 79 additions & 5 deletions Sources/Commands/Components/DeployCommand.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import Foundation
import Minifier

@main
internal struct DeployCommand {

internal enum BundleOption {

case minified
case detailed
}

private static var sourcePath: String {
return CommandLine.arguments[1]
}
Expand All @@ -22,23 +29,30 @@ internal struct DeployCommand {

} else {

try compose(source: sourcePath + "/Resources/css/", to: targetPath + "/htmlkit/", with: "all.css")
try bundle(css: sourcePath + "/Resources/css/", to: targetPath + "/htmlkit/", with: "all.css")

try compose(source: sourcePath + "/Resources/js/", to: targetPath + "/htmlkit/", with: "all.js")
try bundle(js: sourcePath + "/Resources/js/components/", to: targetPath + "/htmlkit/", with: "all.js")

try bundle(js: sourcePath + "/Resources/js/interactions/", to: targetPath + "/htmlkit/", with: "query.js")

exit(0)
}
}

/// Iterates through the directory and collects data to create a single file
private static func compose(source: String, to target: String, with filename: String) throws {
private static func bundle(css source: String, to target: String, with filename: String, option: BundleOption = .minified) throws {

let template = """
@charset "utf-8";
/* Copyright (c) 2019 - 2023 Vapor Community - Licensed under MIT (https://github.com/vapor-community/HTMLKit/blob/main/LICENSE) */
"""

if !manager.fileExists(atPath: target) {
try manager.createDirectory(atPath: target, withIntermediateDirectories: true)
}

if !manager.fileExists(atPath: target + filename) {
manager.createFile(atPath: target + filename, contents: nil)
manager.createFile(atPath: target + filename, contents: template.data(using: .utf8))
}

if let enumerator = manager.enumerator(at: URL(fileURLWithPath: source), includingPropertiesForKeys: nil, options: [.skipsHiddenFiles]) {
Expand All @@ -56,7 +70,67 @@ internal struct DeployCommand {

handle.seekToEndOfFile()

handle.write(try Data(contentsOf: path))
if case .minified = option {

let minifier = Minifier(compression: [.stripComments, .removeWhitespaces])

if let data = minifier.minify(css: try String(contentsOf: path)).data(using: .utf8) {
handle.write(data)
}

} else {
handle.write(try Data(contentsOf: path))
}

handle.closeFile()
}
}
}
}
}
}

/// Iterates through the directory and collects data to create a single file
private static func bundle(js source: String, to target: String, with filename: String, option: BundleOption = .minified) throws {

let template = """
/* Copyright (c) 2019 - 2023 Vapor Community - Licensed under MIT (https://github.com/vapor-community/HTMLKit/blob/main/LICENSE) */
"""

if !manager.fileExists(atPath: target) {
try manager.createDirectory(atPath: target, withIntermediateDirectories: true)
}

if !manager.fileExists(atPath: target + filename) {
manager.createFile(atPath: target + filename, contents: template.data(using: .utf8))
}

if let enumerator = manager.enumerator(at: URL(fileURLWithPath: source), includingPropertiesForKeys: nil, options: [.skipsHiddenFiles]) {

for case let path as URL in enumerator {

if !path.hasDirectoryPath {

if !path.isFileURL {
enumerator.skipDescendants()

} else {

if let handle = FileHandle(forWritingAtPath: target + filename) {

handle.seekToEndOfFile()

if case .minified = option {

let minifier = Minifier(compression: [.stripComments, .removeWhitespaces])

if let data = minifier.minify(js: try String(contentsOf: path)).data(using: .utf8) {
handle.write(data)
}

} else {
handle.write(try Data(contentsOf: path))
}

handle.closeFile()
}
Expand Down
18 changes: 18 additions & 0 deletions Sources/HTMLKit/Abstraction/Attributes/BasicAttributes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2622,3 +2622,21 @@ extension SelectedAttribute where Self: EmptyNode {
return self.mutate(key: "selected", value: value)
}
}

/// The protocol provides the element with the shadowrootmode handler.
public protocol ShadowRootModeAttribute: Attribute {

/// The function represents the html-attribute 'shadowrootmode'.
///
/// ```html
/// <tag shadowrootmode="" />
/// ```
func shadowRootMode(_ value: Values.Shadow.Mode) -> Self
}

extension ShadowRootModeAttribute where Self: ContentNode {

internal func mutate(shadowrootmode value: String) -> Self {
return self.mutate(key: "shadowrootmode", value: value)
}
}
72 changes: 54 additions & 18 deletions Sources/HTMLKit/Abstraction/Attributes/VectorAttributes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -182,24 +182,24 @@ public protocol PositionPointAttribute: Attribute {
/// ```html
/// <tag x="" y="" />
/// ```
func positionPoint(_ point: Geometrics.Point) -> Self
func positionPoint(_ point: (Int, Int)) -> Self
}

extension PositionPointAttribute where Self: ContentNode {

internal func mutate(radius: Geometrics.Point) -> Self {
internal func mutate(positionpoint: (Int, Int)) -> Self {

guard var attributes = self.attributes else {

var attributes = OrderedDictionary<String, Any>()
attributes["x"] = radius.x
attributes["y"] = radius.y
attributes["x"] = positionpoint.0
attributes["y"] = positionpoint.1

return .init(attributes: attributes, content: content)
}

attributes["x"] = radius.x
attributes["y"] = radius.y
attributes["x"] = positionpoint.0
attributes["y"] = positionpoint.1

return .init(attributes: attributes, content: content)
}
Expand All @@ -213,24 +213,24 @@ public protocol RadiusPointAttribute: Attribute {
/// ```html
/// <tag rx="" ry="" />
/// ```
func radiusPoint(_ point: Geometrics.Point) -> Self
func radiusPoint(_ point: (Int, Int)) -> Self
}

extension RadiusPointAttribute where Self: ContentNode {

internal func mutate(radius: Geometrics.Point) -> Self {
internal func mutate(radiuspoint: (Int, Int)) -> Self {

guard var attributes = self.attributes else {

var attributes = OrderedDictionary<String, Any>()
attributes["rx"] = radius.x
attributes["ry"] = radius.y
attributes["rx"] = radiuspoint.0
attributes["ry"] = radiuspoint.1

return .init(attributes: attributes, content: content)
}

attributes["rx"] = radius.x
attributes["ry"] = radius.y
attributes["rx"] = radiuspoint.0
attributes["ry"] = radiuspoint.1

return .init(attributes: attributes, content: content)
}
Expand All @@ -244,24 +244,24 @@ public protocol CenterPointAttribute: Attribute {
/// ```html
/// <tag cx="" cy="" />
/// ```
func centerPoint(_ point: Geometrics.Point) -> Self
func centerPoint(_ point: (Int, Int)) -> Self
}

extension CenterPointAttribute where Self: ContentNode {

internal func mutate(centerpoint: Geometrics.Point) -> Self {
internal func mutate(centerpoint: (Int, Int)) -> Self {

guard var attributes = self.attributes else {

var attributes = OrderedDictionary<String, Any>()
attributes["cx"] = centerpoint.x
attributes["cy"] = centerpoint.y
attributes["cx"] = centerpoint.0
attributes["cy"] = centerpoint.1

return .init(attributes: attributes, content: content)
}

attributes["cx"] = centerpoint.x
attributes["cy"] = centerpoint.y
attributes["cx"] = centerpoint.0
attributes["cy"] = centerpoint.1

return .init(attributes: attributes, content: content)
}
Expand All @@ -284,3 +284,39 @@ extension ViewBoxAttribute where Self: ContentNode {
return self.mutate(key: "viewbox", value: value)
}
}

/// The protocol provides the element with the viewbox handler.
public protocol NamespaceAttribute: Attribute {

/// The function represents the html-attribute 'viewbox'.
///
/// ```html
/// <tag viewbox="" />
/// ```
func namespace(_ value: String) -> Self
}

extension NamespaceAttribute where Self: ContentNode {

internal func mutate(namespace value: String) -> Self {
return self.mutate(key: "xmlns", value: value)
}
}

/// The protocol provides the element with the viewbox handler.
public protocol PointsAttribute: Attribute {

/// The function represents the html-attribute 'viewbox'.
///
/// ```html
/// <tag viewbox="" />
/// ```
func points(_ value: String) -> Self
}

extension PointsAttribute where Self: ContentNode {

internal func mutate(points value: String) -> Self {
return self.mutate(key: "points", value: value)
}
}
Loading

0 comments on commit e919e51

Please sign in to comment.