diff --git a/android/Gutenberg/src/main/java/org/wordpress/gutenberg/EditorConfiguration.kt b/android/Gutenberg/src/main/java/org/wordpress/gutenberg/EditorConfiguration.kt index b71b944c..be3c319b 100644 --- a/android/Gutenberg/src/main/java/org/wordpress/gutenberg/EditorConfiguration.kt +++ b/android/Gutenberg/src/main/java/org/wordpress/gutenberg/EditorConfiguration.kt @@ -3,48 +3,6 @@ package org.wordpress.gutenberg import android.os.Parcelable import kotlinx.parcelize.Parcelize -@Parcelize -sealed class WebViewGlobalValue : Parcelable { - @Parcelize - data class StringValue(val value: String) : WebViewGlobalValue() - @Parcelize - data class NumberValue(val value: Double) : WebViewGlobalValue() - @Parcelize - data class BooleanValue(val value: Boolean) : WebViewGlobalValue() - @Parcelize - data class ObjectValue(val value: Map) : WebViewGlobalValue() - @Parcelize - data class ArrayValue(val value: List) : WebViewGlobalValue() - @Parcelize - object NullValue : WebViewGlobalValue() - - fun toJavaScript(): String { - return when (this) { - is StringValue -> "\"${value.replace("\"", "\\\"").replace("\n", "\\n").replace("\r", "\\r").replace("\t", "\\t")}\"" - is NumberValue -> value.toString() - is BooleanValue -> value.toString() - is ObjectValue -> { - val pairs = value.map { (key, value) -> "\"$key\": ${value.toJavaScript()}" } - "{${pairs.joinToString(",")}}" - } - is ArrayValue -> "[${value.joinToString(",") { it.toJavaScript() }}]" - is NullValue -> "null" - } - } -} - -@Parcelize -data class WebViewGlobal( - val name: String, - val value: WebViewGlobalValue -) : Parcelable { - init { - require(name.matches(Regex("^[a-zA-Z_$][a-zA-Z0-9_$]*$"))) { - "Invalid JavaScript identifier: $name" - } - } -} - @Parcelize open class EditorConfiguration constructor( val title: String, @@ -59,7 +17,6 @@ open class EditorConfiguration constructor( val siteApiNamespace: Array, val namespaceExcludedPaths: Array, val authHeader: String, - val webViewGlobals: List, val editorSettings: String?, val locale: String?, val cookies: Map, @@ -85,7 +42,6 @@ open class EditorConfiguration constructor( private var siteApiNamespace: Array = arrayOf() private var namespaceExcludedPaths: Array = arrayOf() private var authHeader: String = "" - private var webViewGlobals: List = emptyList() private var editorSettings: String? = null private var locale: String? = "en" private var cookies: Map = mapOf() @@ -105,7 +61,6 @@ open class EditorConfiguration constructor( fun setSiteApiNamespace(siteApiNamespace: Array) = apply { this.siteApiNamespace = siteApiNamespace } fun setNamespaceExcludedPaths(namespaceExcludedPaths: Array) = apply { this.namespaceExcludedPaths = namespaceExcludedPaths } fun setAuthHeader(authHeader: String) = apply { this.authHeader = authHeader } - fun setWebViewGlobals(webViewGlobals: List) = apply { this.webViewGlobals = webViewGlobals } fun setEditorSettings(editorSettings: String?) = apply { this.editorSettings = editorSettings } fun setLocale(locale: String?) = apply { this.locale = locale } fun setCookies(cookies: Map) = apply { this.cookies = cookies } @@ -126,7 +81,6 @@ open class EditorConfiguration constructor( siteApiNamespace = siteApiNamespace, namespaceExcludedPaths = namespaceExcludedPaths, authHeader = authHeader, - webViewGlobals = webViewGlobals, editorSettings = editorSettings, locale = locale, cookies = cookies, @@ -154,7 +108,6 @@ open class EditorConfiguration constructor( if (!siteApiNamespace.contentEquals(other.siteApiNamespace)) return false if (!namespaceExcludedPaths.contentEquals(other.namespaceExcludedPaths)) return false if (authHeader != other.authHeader) return false - if (webViewGlobals != other.webViewGlobals) return false if (editorSettings != other.editorSettings) return false if (locale != other.locale) return false if (cookies != other.cookies) return false @@ -178,7 +131,6 @@ open class EditorConfiguration constructor( result = 31 * result + siteApiNamespace.contentHashCode() result = 31 * result + namespaceExcludedPaths.contentHashCode() result = 31 * result + authHeader.hashCode() - result = 31 * result + webViewGlobals.hashCode() result = 31 * result + (editorSettings?.hashCode() ?: 0) result = 31 * result + (locale?.hashCode() ?: 0) result = 31 * result + cookies.hashCode() diff --git a/android/Gutenberg/src/main/java/org/wordpress/gutenberg/GutenbergView.kt b/android/Gutenberg/src/main/java/org/wordpress/gutenberg/GutenbergView.kt index 4b4e166a..8a3f9356 100644 --- a/android/Gutenberg/src/main/java/org/wordpress/gutenberg/GutenbergView.kt +++ b/android/Gutenberg/src/main/java/org/wordpress/gutenberg/GutenbergView.kt @@ -294,11 +294,6 @@ class GutenbergView : WebView { } private fun setGlobalJavaScriptVariables() { - // Generate JavaScript globals - val globalsJS = configuration.webViewGlobals.map { global -> - "window[\"${global.name}\"] = ${global.value.toJavaScript()};" - }.joinToString("\n") - val escapedTitle = encodeForEditor(configuration.title) val escapedContent = encodeForEditor(configuration.content) val editorSettings = configuration.editorSettings ?: "undefined" @@ -325,13 +320,7 @@ class GutenbergView : WebView { localStorage.setItem('GBKit', JSON.stringify(window.GBKit)); """.trimIndent() - val combinedJS = if (globalsJS.isNotEmpty()) { - "$globalsJS\n$gbKitConfig" - } else { - gbKitConfig - } - - this.evaluateJavascript(combinedJS, null) + this.evaluateJavascript(gbKitConfig, null) } private fun encodeForEditor(value: String): String { diff --git a/android/Gutenberg/src/test/java/org/wordpress/gutenberg/EditorConfigurationTest.kt b/android/Gutenberg/src/test/java/org/wordpress/gutenberg/EditorConfigurationTest.kt index 02ae5466..74e972fa 100644 --- a/android/Gutenberg/src/test/java/org/wordpress/gutenberg/EditorConfigurationTest.kt +++ b/android/Gutenberg/src/test/java/org/wordpress/gutenberg/EditorConfigurationTest.kt @@ -22,11 +22,6 @@ class EditorConfigurationTest { .setSiteApiNamespace(arrayOf("wp/v2")) .setNamespaceExcludedPaths(arrayOf("users")) .setAuthHeader("Bearer token") - .setWebViewGlobals(listOf( - WebViewGlobal("testString", WebViewGlobalValue.StringValue("test")), - WebViewGlobal("testNumber", WebViewGlobalValue.NumberValue(42.0)), - WebViewGlobal("testBoolean", WebViewGlobalValue.BooleanValue(true)) - )) .build() } @@ -44,60 +39,6 @@ class EditorConfigurationTest { assertArrayEquals(arrayOf("wp/v2"), editorConfig.siteApiNamespace) assertArrayEquals(arrayOf("users"), editorConfig.namespaceExcludedPaths) assertEquals("Bearer token", editorConfig.authHeader) - assertEquals(3, editorConfig.webViewGlobals.size) - } - - @Test - fun `test WebViewGlobal StringValue toJavaScript conversion`() { - val stringValue = WebViewGlobalValue.StringValue("test\nvalue") - assertEquals("\"test\\nvalue\"", stringValue.toJavaScript()) - } - - @Test - fun `test WebViewGlobal NumberValue toJavaScript conversion`() { - val numberValue = WebViewGlobalValue.NumberValue(42.0) - assertEquals("42.0", numberValue.toJavaScript()) - } - - @Test - fun `test WebViewGlobal BooleanValue toJavaScript conversion`() { - val booleanValue = WebViewGlobalValue.BooleanValue(true) - assertEquals("true", booleanValue.toJavaScript()) - } - - @Test - fun `test WebViewGlobal ObjectValue toJavaScript conversion`() { - val objectValue = WebViewGlobalValue.ObjectValue(mapOf( - "key1" to WebViewGlobalValue.StringValue("value1"), - "key2" to WebViewGlobalValue.NumberValue(42.0) - )) - assertEquals("{\"key1\": \"value1\",\"key2\": 42.0}", objectValue.toJavaScript()) - } - - @Test - fun `test WebViewGlobal ArrayValue toJavaScript conversion`() { - val arrayValue = WebViewGlobalValue.ArrayValue(listOf( - WebViewGlobalValue.StringValue("value1"), - WebViewGlobalValue.NumberValue(42.0) - )) - assertEquals("[\"value1\",42.0]", arrayValue.toJavaScript()) - } - - @Test - fun `test WebViewGlobal NullValue toJavaScript conversion`() { - val nullValue = WebViewGlobalValue.NullValue - assertEquals("null", nullValue.toJavaScript()) - } - - @Test - fun `test WebViewGlobal valid identifier`() { - val validGlobal = WebViewGlobal("validName", WebViewGlobalValue.StringValue("test")) - assertEquals("validName", validGlobal.name) - } - - @Test(expected = IllegalArgumentException::class) - fun `test WebViewGlobal invalid identifier throws exception`() { - WebViewGlobal("123invalid", WebViewGlobalValue.StringValue("test")) } @Test @@ -130,4 +71,4 @@ class EditorConfigurationTest { assertNotEquals(config1, config2) } -} +} \ No newline at end of file diff --git a/android/app/src/main/java/com/example/gutenbergkit/MainActivity.kt b/android/app/src/main/java/com/example/gutenbergkit/MainActivity.kt index c034444b..d601ed6d 100644 --- a/android/app/src/main/java/com/example/gutenbergkit/MainActivity.kt +++ b/android/app/src/main/java/com/example/gutenbergkit/MainActivity.kt @@ -74,7 +74,6 @@ class MainActivity : AppCompatActivity(), AuthenticationManager.AuthenticationCa .setSiteApiNamespace(arrayOf()) .setNamespaceExcludedPaths(arrayOf()) .setAuthHeader("") - .setWebViewGlobals(emptyList()) .setCookies(emptyMap()) .build() @@ -94,7 +93,6 @@ class MainActivity : AppCompatActivity(), AuthenticationManager.AuthenticationCa .setPostType("post") .setThemeStyles(false) .setHideTitle(false) - .setWebViewGlobals(emptyList()) .setCookies(emptyMap()) private fun launchEditor(configuration: EditorConfiguration) { diff --git a/ios/Sources/GutenbergKit/Sources/EditorConfiguration.swift b/ios/Sources/GutenbergKit/Sources/EditorConfiguration.swift index 87c3446e..11a739fc 100644 --- a/ios/Sources/GutenbergKit/Sources/EditorConfiguration.swift +++ b/ios/Sources/GutenbergKit/Sources/EditorConfiguration.swift @@ -16,7 +16,6 @@ public struct EditorConfiguration { public var siteApiNamespace: [String] = [] public var namespaceExcludedPaths: [String] = [] public var authHeader = "" - public var webViewGlobals: [WebViewGlobal] = [] /// Raw block editor settings from the WordPress REST API public var editorSettings: [String: Any]? /// The locale to use for translations @@ -34,67 +33,3 @@ public struct EditorConfiguration { public static let `default` = EditorConfiguration() } - -public struct WebViewGlobal { - let name: String - let value: WebViewGlobalValue - - public init(name: String, value: WebViewGlobalValue) throws { - // Validate name is a valid JavaScript identifier - guard Self.isValidJavaScriptIdentifier(name) else { - throw WebViewGlobalError.invalidIdentifier(name) - } - self.name = name - self.value = value - } - - private static func isValidJavaScriptIdentifier(_ name: String) -> Bool { - // Add validation logic for JavaScript identifiers - return name.range(of: "^[a-zA-Z_$][a-zA-Z0-9_$]*$", options: .regularExpression) != nil - } -} - -public enum WebViewGlobalError: Error { - case invalidIdentifier(String) -} - -public enum WebViewGlobalValue { - case string(String) - case number(Double) - case boolean(Bool) - case object([String: WebViewGlobalValue]) - case array([WebViewGlobalValue]) - case null - - func toJavaScript() -> String { - switch self { - case .string(let str): - return "\"\(str.escaped)\"" - case .number(let num): - return "\(num)" - case .boolean(let bool): - return "\(bool)" - case .object(let dict): - let pairs = dict.map { key, value in - "\"\(key.escaped)\": \(value.toJavaScript())" - } - return "{\(pairs.joined(separator: ","))}" - case .array(let array): - return "[\(array.map { $0.toJavaScript() }.joined(separator: ","))]" - case .null: - return "null" - } - } -} - -// String escaping extension -private extension String { - var escaped: String { - return self.replacingOccurrences(of: "\"", with: "\\\"") - .replacingOccurrences(of: "\n", with: "\\n") - .replacingOccurrences(of: "\r", with: "\\r") - .replacingOccurrences(of: "\t", with: "\\t") - .replacingOccurrences(of: "\u{8}", with: "\\b") - .replacingOccurrences(of: "\u{12}", with: "\\f") - } -} diff --git a/ios/Sources/GutenbergKit/Sources/EditorViewController.swift b/ios/Sources/GutenbergKit/Sources/EditorViewController.swift index f837b3f0..e7d13de4 100644 --- a/ios/Sources/GutenbergKit/Sources/EditorViewController.swift +++ b/ios/Sources/GutenbergKit/Sources/EditorViewController.swift @@ -146,11 +146,6 @@ public final class EditorViewController: UIViewController, GutenbergEditorContro let escapedTitle = configuration.title.addingPercentEncoding(withAllowedCharacters: .alphanumerics)! let escapedContent = configuration.content.addingPercentEncoding(withAllowedCharacters: .alphanumerics)! - // Generate JavaScript globals - let globalsJS = configuration.webViewGlobals.map { global in - "window[\"\(global.name)\"] = \(global.value.toJavaScript());" - }.joined(separator: "\n") - // Convert editor settings to JSON string if available var editorSettingsJS = "undefined" if let settings = configuration.editorSettings { @@ -165,8 +160,6 @@ public final class EditorViewController: UIViewController, GutenbergEditorContro } let jsCode = """ - \(globalsJS) - window.GBKit = { siteURL: '\(configuration.siteURL)', siteApiRoot: '\(configuration.siteApiRoot)', diff --git a/ios/Tests/GutenbergKitTests/EditorConfigurationTests.swift b/ios/Tests/GutenbergKitTests/EditorConfigurationTests.swift deleted file mode 100644 index 29e451f8..00000000 --- a/ios/Tests/GutenbergKitTests/EditorConfigurationTests.swift +++ /dev/null @@ -1,117 +0,0 @@ -import XCTest -@testable import GutenbergKit - -final class EditorConfigurationTests: XCTestCase { - - // MARK: - WebViewGlobal Tests - - func testValidJavaScriptIdentifiers() { - let validIdentifiers = [ - "myVar", - "_privateVar", - "$jQuery", - "myVar123", - "MY_CONSTANT", - "a", - "A" - ] - - for identifier in validIdentifiers { - XCTAssertNoThrow(try WebViewGlobal(name: identifier, value: .string("test"))) - } - } - - func testInvalidJavaScriptIdentifiers() { - let invalidIdentifiers = [ - "123invalid", - "my-var", - "my.var", - "my var", - "", - "my@var", - "my#var" - ] - - for identifier in invalidIdentifiers { - XCTAssertThrowsError(try WebViewGlobal(name: identifier, value: .string("test"))) - } - } - - // MARK: - WebViewGlobalValue Tests - - func testStringValueConversion() { - let testCases = [ - ("simple", "\"simple\""), - ("with \"quotes\"", "\"with \\\"quotes\\\"\""), - ("with\nnewline", "\"with\\nnewline\""), - ("with\ttab", "\"with\\ttab\""), - ("with\rreturn", "\"with\\rreturn\""), - ("with\u{8}backspace", "\"with\\bbackspace\""), - ("with\u{12}formfeed", "\"with\\fformfeed\"") - ] - - for (input, expected) in testCases { - let value = WebViewGlobalValue.string(input) - XCTAssertEqual(value.toJavaScript(), expected) - } - } - - func testNumberValueConversion() { - let testCases = [ - (42.0, "42.0"), - (-3.14, "-3.14"), - (0.0, "0.0"), - (1.0, "1.0") - ] - - for (input, expected) in testCases { - let value = WebViewGlobalValue.number(input) - XCTAssertEqual(value.toJavaScript(), expected) - } - } - - func testBooleanValueConversion() { - XCTAssertEqual(WebViewGlobalValue.boolean(true).toJavaScript(), "true") - XCTAssertEqual(WebViewGlobalValue.boolean(false).toJavaScript(), "false") - } - - func testNullValueConversion() { - XCTAssertEqual(WebViewGlobalValue.null.toJavaScript(), "null") - } - - func testObjectValueConversion() { - let object = WebViewGlobalValue.object([ - "name": .string("test"), - "count": .number(42), - "active": .boolean(true), - "nested": .object([ - "value": .string("nested") - ]) - ]) - - let actual = object.toJavaScript() - let expected = "{\"name\": \"test\",\"active\": true,\"count\": 42.0,\"nested\": {\"value\": \"nested\"}}" - - guard let actualData = actual.data(using: .utf8), - let expectedData = expected.data(using: .utf8), - let actualJSON = try? JSONSerialization.jsonObject(with: actualData) as? [String: Any], - let expectedJSON = try? JSONSerialization.jsonObject(with: expectedData) as? [String: Any] else { - XCTFail("Failed to parse JSON") - return - } - - XCTAssertEqual(actualJSON as NSDictionary, expectedJSON as NSDictionary) - } - - func testArrayValueConversion() { - let array = WebViewGlobalValue.array([ - .string("test"), - .number(42), - .boolean(true), - .null - ]) - - let expected = "[\"test\",42.0,true,null]" - XCTAssertEqual(array.toJavaScript(), expected) - } -}