diff --git a/ios/Sources/GutenbergKit/Sources/EditorConfiguration.swift b/ios/Sources/GutenbergKit/Sources/EditorConfiguration.swift index 33b6f57a..93694e46 100644 --- a/ios/Sources/GutenbergKit/Sources/EditorConfiguration.swift +++ b/ios/Sources/GutenbergKit/Sources/EditorConfiguration.swift @@ -32,6 +32,8 @@ public struct EditorConfiguration: Sendable { public let locale: String /// Enables the native inserter UI in the editor public let isNativeInserterEnabled: Bool + /// Endpoint for loading editor settings + public let editorSettingsEndpoint: URL? /// Endpoint for loading editor assets, used when enabling `shouldUsePlugins` public let editorAssetsEndpoint: URL? /// Logs emitted at or above this level will be printed to the debug console @@ -56,6 +58,7 @@ public struct EditorConfiguration: Sendable { editorSettings: String, locale: String, isNativeInserterEnabled: Bool, + editorSettingsEndpoint: URL?, editorAssetsEndpoint: URL?, logLevel: EditorLogLevel, enableNetworkLogging: Bool = false @@ -75,6 +78,7 @@ public struct EditorConfiguration: Sendable { self.editorSettings = editorSettings self.locale = locale self.isNativeInserterEnabled = isNativeInserterEnabled + self.editorSettingsEndpoint = editorSettingsEndpoint self.editorAssetsEndpoint = editorAssetsEndpoint self.logLevel = logLevel self.enableNetworkLogging = enableNetworkLogging @@ -97,6 +101,7 @@ public struct EditorConfiguration: Sendable { editorSettings: editorSettings, locale: locale, isNativeInserterEnabled: isNativeInserterEnabled, + editorSettingsEndpoint: editorSettingsEndpoint, editorAssetsEndpoint: editorAssetsEndpoint, logLevel: logLevel, enableNetworkLogging: enableNetworkLogging @@ -130,6 +135,7 @@ public struct EditorConfigurationBuilder { private var editorSettings: String private var locale: String private var isNativeInserterEnabled: Bool + private var editorSettingsEndpoint: URL? private var editorAssetsEndpoint: URL? private var logLevel: EditorLogLevel private var enableNetworkLogging: Bool @@ -150,6 +156,7 @@ public struct EditorConfigurationBuilder { editorSettings: String = "undefined", locale: String = "en", isNativeInserterEnabled: Bool = false, + editorSettingsEndpoint: URL? = nil, editorAssetsEndpoint: URL? = nil, logLevel: EditorLogLevel = .error, enableNetworkLogging: Bool = false @@ -169,6 +176,7 @@ public struct EditorConfigurationBuilder { self.editorSettings = editorSettings self.locale = locale self.isNativeInserterEnabled = isNativeInserterEnabled + self.editorSettingsEndpoint = editorSettingsEndpoint self.editorAssetsEndpoint = editorAssetsEndpoint self.logLevel = logLevel self.enableNetworkLogging = enableNetworkLogging @@ -264,6 +272,12 @@ public struct EditorConfigurationBuilder { return copy } + public func setEditorSettingsEndpoint(_ editorSettingsEndpoint: URL?) -> EditorConfigurationBuilder { + var copy = self + copy.editorSettingsEndpoint = editorSettingsEndpoint + return copy + } + public func setEditorAssetsEndpoint(_ editorAssetsEndpoint: URL?) -> EditorConfigurationBuilder { var copy = self copy.editorAssetsEndpoint = editorAssetsEndpoint @@ -321,6 +335,7 @@ public struct EditorConfigurationBuilder { editorSettings: editorSettings, locale: locale, isNativeInserterEnabled: isNativeInserterEnabled, + editorSettingsEndpoint: editorSettingsEndpoint, editorAssetsEndpoint: editorAssetsEndpoint, logLevel: logLevel, enableNetworkLogging: enableNetworkLogging diff --git a/ios/Sources/GutenbergKit/Sources/Service/EditorService.swift b/ios/Sources/GutenbergKit/Sources/Service/EditorService.swift index 62b4830a..5908a1ea 100644 --- a/ios/Sources/GutenbergKit/Sources/Service/EditorService.swift +++ b/ios/Sources/GutenbergKit/Sources/Service/EditorService.swift @@ -153,7 +153,7 @@ public actor EditorService { // Fetch settings and manifest in parallel async let settingsFuture = Result { - try await fetchEditorSettings(baseURL: baseURL, authHeader: configuration.authHeader) + try await fetchEditorSettings(configuration: configuration) } async let manifestFuture = Result { try await fetchManifestData(configuration: configuration) @@ -203,8 +203,9 @@ public actor EditorService { /// /// - Returns: Raw settings data from the API @discardableResult - private func fetchEditorSettings(baseURL: URL, authHeader: String) async throws -> Data { - let data = try await fetchData(for: baseURL.appendingPathComponent("/wp-block-editor/v1/settings"), authHeader: authHeader) + private func fetchEditorSettings(configuration: EditorConfiguration) async throws -> Data { + let endpoint = try configuration.makeEditorSettingsEndpointURL() + let data = try await fetchData(for: endpoint, authHeader: configuration.authHeader) do { FileManager.default.createDirectoryIfNeeded(at: storeURL) try data.write(to: editorSettingsFileURL) @@ -219,7 +220,7 @@ public actor EditorService { /// Fetches the editor assets manifest from the WordPress REST API /// Does not write to disk - use this to get manifest data without persisting it private func fetchManifestData(configuration: EditorConfiguration) async throws -> Data { - let endpoint = try configuration.editorAssetsManifestEndpoint() + let endpoint = try configuration.makeEditorAssetsManifestEndpointURL() let data = try await fetchData(for: endpoint, authHeader: configuration.authHeader) return data } @@ -492,18 +493,33 @@ private extension FileManager { } private extension EditorConfiguration { - /// Returns the endpoint URL for fetching the editor assets manifest - func editorAssetsManifestEndpoint() throws -> URL { - if let customEndpoint = editorAssetsEndpoint { + /// Returns the endpoint URL for fetching the editor settings + func makeEditorSettingsEndpointURL() throws -> URL { + if let customEndpoint = editorSettingsEndpoint { return customEndpoint } // Fall back to constructing endpoint from siteApiRoot guard let baseURL = URL(string: siteApiRoot) else { throw URLError(.badURL) } + return baseURL.appendingPathComponent("/wp-block-editor/v1/settings") + } + + /// Returns the endpoint URL for fetching the editor assets manifest + func makeEditorAssetsManifestEndpointURL() throws -> URL { + let endpoint: URL + if let customEndpoint = editorAssetsEndpoint { + endpoint = customEndpoint + } else { + // Fall back to constructing endpoint from siteApiRoot + guard let baseURL = URL(string: siteApiRoot) else { + throw URLError(.badURL) + } + endpoint = baseURL.appendingPathComponent("/wpcom/v2/editor-assets") + } + + // Always add query parameters let excludeParam = URLQueryItem(name: "exclude", value: "core,gutenberg") - return baseURL - .appendingPathComponent("/wpcom/v2/editor-assets") - .appending(queryItems: [excludeParam]) + return endpoint.appending(queryItems: [excludeParam]) } }