From 84787879033912c609bfa44b97423b41f1e82280 Mon Sep 17 00:00:00 2001 From: Kenta Kubo Date: Thu, 17 Mar 2022 01:22:29 +0900 Subject: [PATCH 1/3] Add HTML Encoder / Decoder --- Package.resolved | 9 +++ Package.swift | 6 +- .../HTMLEncoderDecoderViewModel.swift | 29 +++++++++ Sources/DevToysApp/Views/AllToolsView.swift | 20 ++++++ .../HTMLEncoderDecoderView.swift | 64 +++++++++++++++++++ Sources/DevToysApp/Views/Sidebar.swift | 18 ++++++ 6 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 Sources/DevToysApp/ViewModels/EncodersDecoders/HTMLEncoderDecoderViewModel.swift create mode 100644 Sources/DevToysApp/Views/EncodersDecoders/HTMLEncoderDecoderView.swift diff --git a/Package.resolved b/Package.resolved index 9e98357..f5bfcf6 100644 --- a/Package.resolved +++ b/Package.resolved @@ -10,6 +10,15 @@ "version": "2.6.3" } }, + { + "package": "HTMLEntities", + "repositoryURL": "https://github.com/Kitura/swift-html-entities", + "state": { + "branch": null, + "revision": "3686a2b931be24dd2531307f89e2f1d648c0200e", + "version": "4.0.0" + } + }, { "package": "swift-log", "repositoryURL": "https://github.com/apple/swift-log.git", diff --git a/Package.swift b/Package.swift index 0912505..d9f57a6 100644 --- a/Package.swift +++ b/Package.swift @@ -35,7 +35,8 @@ let package = Package( dependencies: [ .package(url: "https://github.com/kkk669/swift-log-playground", "0.1.0"..<"0.2.0"), .package(url: "https://github.com/luin/SwiftJSONFormatter", "1.0.0"..<"1.1.0"), - .package(url: "https://github.com/auth0/JWTDecode.swift", "2.6.3"..<"2.7.0") + .package(url: "https://github.com/auth0/JWTDecode.swift", "2.6.3"..<"2.7.0"), + .package(url: "https://github.com/Kitura/swift-html-entities", "4.0.0"..<"4.1.0") ], targets: [ .executableTarget( @@ -43,7 +44,8 @@ let package = Package( dependencies: [ .product(name: "LoggingPlayground", package: "swift-log-playground"), .product(name: "SwiftJSONFormatter", package: "SwiftJSONFormatter"), - .product(name: "JWTDecode", package: "JWTDecode.swift") + .product(name: "JWTDecode", package: "JWTDecode.swift"), + .product(name: "HTMLEntities", package: "swift-html-entities") ], swiftSettings: [ .unsafeFlags(["-Xfrontend", "-warn-long-function-bodies=100"], .when(configuration: .debug)), diff --git a/Sources/DevToysApp/ViewModels/EncodersDecoders/HTMLEncoderDecoderViewModel.swift b/Sources/DevToysApp/ViewModels/EncodersDecoders/HTMLEncoderDecoderViewModel.swift new file mode 100644 index 0000000..e46f5db --- /dev/null +++ b/Sources/DevToysApp/ViewModels/EncodersDecoders/HTMLEncoderDecoderViewModel.swift @@ -0,0 +1,29 @@ +import Combine +import HTMLEntities + +final class HTMLEncoderDecoderViewModel { + @Published var encodeMode = true + @Published var input = "" + @Published var output = "" + + init() { + self.$input.combineLatest(self.$encodeMode) + .dropFirst() + .map { input, encodeMode in + encodeMode + ? Self.encode(input) + : Self.decode(input) + } + .assign(to: &self.$output) + } + + private static func encode(_ input: String) -> String { + input.htmlEscape(useNamedReferences: true) + } + + private static func decode(_ input: String) -> String { + input.htmlUnescape() + } +} + +extension HTMLEncoderDecoderViewModel: ObservableObject {} diff --git a/Sources/DevToysApp/Views/AllToolsView.swift b/Sources/DevToysApp/Views/AllToolsView.swift index 4dad3ea..0528975 100644 --- a/Sources/DevToysApp/Views/AllToolsView.swift +++ b/Sources/DevToysApp/Views/AllToolsView.swift @@ -85,6 +85,26 @@ extension AllToolsView: View { } } } + if !self.isSearching + || self.searchQuery.isEmpty + || "HTML Encoder / Decoder".lowercased() + .contains(self.searchQuery.lowercased()) + { + NavigationLink { + HTMLEncoderDecoderView() + } label: { + Label { + Text("HTML") + Text( + "Encode or decode all the applicable characters to their corresponding HTML entities" + ) + .font(.caption) + .foregroundStyle(.secondary) + } icon: { + Image(systemName: "chevron.left.slash.chevron.right") + } + } + } if !self.isSearching || self.searchQuery.isEmpty || "JSON Formatter".lowercased() diff --git a/Sources/DevToysApp/Views/EncodersDecoders/HTMLEncoderDecoderView.swift b/Sources/DevToysApp/Views/EncodersDecoders/HTMLEncoderDecoderView.swift new file mode 100644 index 0000000..bd89f1f --- /dev/null +++ b/Sources/DevToysApp/Views/EncodersDecoders/HTMLEncoderDecoderView.swift @@ -0,0 +1,64 @@ +import SwiftUI + +struct HTMLEncoderDecoderView { + @StateObject private var viewModel = HTMLEncoderDecoderViewModel() + + init() { + Task { @MainActor in + UITextView.appearance().backgroundColor = .clear + } + } +} + +extension HTMLEncoderDecoderView: View { + var body: some View { + ToyPage { + ToySection("Configuration") { + ConfigurationRow(systemImage: "arrow.left.arrow.right") { + Text("Conversion") + Text("Select which conversion mode you want to use") + .font(.caption) + .foregroundStyle(.secondary) + } content: { + Picker("", selection: self.$viewModel.encodeMode) { + Text("Encode").tag(true) + Text("Decode").tag(false) + } + } + } + + ToySection("Input") { + PasteButton(text: self.$viewModel.input) + OpenFileButton(text: self.$viewModel.input) + ClearButton(text: self.$viewModel.input) + } content: { + TextEditor(text: self.$viewModel.input) + .disableAutocorrection(true) + .textInputAutocapitalization(.never) + .font(.body.monospaced()) + .background(.regularMaterial) + .cornerRadius(8) + .frame(idealHeight: 200) + } + + ToySection("Output") { + CopyButton(text: self.viewModel.output) + } content: { + TextEditor(text: .constant(self.viewModel.output)) + .disableAutocorrection(true) + .textInputAutocapitalization(.never) + .font(.body.monospaced()) + .background(.regularMaterial) + .cornerRadius(8) + .frame(idealHeight: 200) + } + } + .navigationTitle("HTML Encoder / Decoder") + } +} + +struct HTMLEncoderDecoderView_Previews: PreviewProvider { + static var previews: some View { + HTMLEncoderDecoderView() + } +} diff --git a/Sources/DevToysApp/Views/Sidebar.swift b/Sources/DevToysApp/Views/Sidebar.swift index 631a08d..a69d39e 100644 --- a/Sources/DevToysApp/Views/Sidebar.swift +++ b/Sources/DevToysApp/Views/Sidebar.swift @@ -43,6 +43,14 @@ extension Sidebar: View { Text("Converters").font(.title3.bold()) } Section { + NavigationLink { + HTMLEncoderDecoderView() + } label: { + Label( + "HTML", + systemImage: "chevron.left.slash.chevron.right" + ) + } NavigationLink { URLEncoderDecoderView() } label: { @@ -113,6 +121,16 @@ extension Sidebar: View { Label("Number Base Converter", systemImage: "number.square") } } + if self.isMatch("HTML Encoder / Decoder") { + NavigationLink { + HTMLEncoderDecoderView() + } label: { + Label( + "HTML Encoder / Decoder", + systemImage: "chevron.left.slash.chevron.right" + ) + } + } if self.isMatch("URL Encoder / Decoder") { NavigationLink { URLEncoderDecoderView() From 3abfef5de7435e384898c263886643a1473cb7ad Mon Sep 17 00:00:00 2001 From: Kenta Kubo Date: Thu, 17 Mar 2022 01:26:30 +0900 Subject: [PATCH 2/3] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b6666bc..bce4370 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ This app is a SwiftUI reimplementation of [DevToys](https://devtoys.app), a Swis - [ ] JSON <> YAML - [x] Number Base - Encoders / Decoders - - [ ] HTML + - [x] HTML - [x] URL - [x] Base64 - [ ] GZip From fed287b661ee79b66328e85bc71e08d8f82e6f23 Mon Sep 17 00:00:00 2001 From: Kenta Kubo Date: Thu, 17 Mar 2022 12:43:40 +0900 Subject: [PATCH 3/3] Fix "Build failed because the Mach-O file couldn't be generated" --- Package.resolved | 6 +++--- Package.swift | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Package.resolved b/Package.resolved index f5bfcf6..472eb3f 100644 --- a/Package.resolved +++ b/Package.resolved @@ -12,11 +12,11 @@ }, { "package": "HTMLEntities", - "repositoryURL": "https://github.com/Kitura/swift-html-entities", + "repositoryURL": "https://github.com/kkk669/swift-html-entities", "state": { "branch": null, - "revision": "3686a2b931be24dd2531307f89e2f1d648c0200e", - "version": "4.0.0" + "revision": "39083f7a1826b1b01e3a270795ed409ac4ccea18", + "version": "4.0.1" } }, { diff --git a/Package.swift b/Package.swift index d9f57a6..b5abce0 100644 --- a/Package.swift +++ b/Package.swift @@ -36,7 +36,7 @@ let package = Package( .package(url: "https://github.com/kkk669/swift-log-playground", "0.1.0"..<"0.2.0"), .package(url: "https://github.com/luin/SwiftJSONFormatter", "1.0.0"..<"1.1.0"), .package(url: "https://github.com/auth0/JWTDecode.swift", "2.6.3"..<"2.7.0"), - .package(url: "https://github.com/Kitura/swift-html-entities", "4.0.0"..<"4.1.0") + .package(url: "https://github.com/kkk669/swift-html-entities", "4.0.1"..<"4.1.0") ], targets: [ .executableTarget(