diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..214aaaf9 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,28 @@ +# Contributing to GutenbergKit + +Thank you for your interest in contributing to GutenbergKit! + +## How Can I Contribute? + +Whether you're looking to write code, improve documentation, or help triage issues, there are many ways to contribute: + +- **Code**: See the [Code Contributions](./docs/code/README.md) guide to get started +- **Documentation**: Help improve our [docs](./docs/) +- **Triage**: Review and label [open issues](https://github.com/wordpress-mobile/GutenbergKit/issues) + +## Development Resources + +- [Getting Started](./docs/code/getting-started.md) - Prerequisites and setup +- [Development Tools](./docs/code/development-tools.md) - Debugging and development features +- [Testing](./docs/code/testing.md) - Running tests and code quality +- [Architecture](./docs/code/architecture.md) - Project structure and patterns + +## Guidelines + +- Run `make format` and `make lint-js` before submitting changes +- Ensure tests pass with `make test-js`, `make test-swift-package`, and `make test-android` +- Follow the existing code style and patterns + +## Releases + +See the [release documentation](./docs/releases.md) for information about the release process. diff --git a/README.md b/README.md index d7238a8c..f56f046f 100644 --- a/README.md +++ b/README.md @@ -1,110 +1,30 @@ # GutenbergKit -An experimental Gutenberg block editor for native iOS and Android apps relying upon web technologies. +GutenbergKit running on an iPhone -GutenbergKit running on an iPhone +GutenbergKit brings the [WordPress](https://wordpress.org/) block editor to native mobile applications. It bridges WordPress's web-based [Gutenberg](https://github.com/WordPress/gutenberg/) editor with native iOS and Android apps, enabling a consistent editing experience across platforms. -## Development +The architecture consists of three main layers: -To see all available development commands, run `make help` (or simply `make`) in your terminal. This will display a list of all available build, test, and development commands. +- **Web Layer**: React-based editor using WordPress Gutenberg packages +- **Bridge Layer**: Bidirectional communication between web and native code +- **Native Layer**: Platform-specific implementations (Swift for iOS, Kotlin for Android) -### Preqrequisites +## Getting Started -In order to build GutenbergKit, the following tools must be installed on your development machine: +### Using GutenbergKit -- [Node.js](https://nodejs.org/en/download/) - Required for building the web app; recommend using [Node Version Manager](https://github.com/nvm-sh/nvm). -- [Xcode](https://developer.apple.com/xcode/) - Required if building the iOS demo app. -- [Android Studio](https://developer.android.com/studio) - Required if building the Android demo app. +To integrate GutenbergKit into your iOS or Android app, include the package as a dependency: -### Web App +- **iOS**: Add the Swift package from the repository root +- **Android**: Add the Kotlin library as a Maven dependency or include the `android/Gutenberg/` module -Install the GutenbergKit dependencies and start the development server by running the following command in your terminal: +See the [Integration Guide](./docs/integration.md) for detailed setup instructions and code examples. -```bash -make dev-server -``` +### Contributing -Once finished, the web app can now be accessed in your browser by visiting the URL logged in your terminal. However, it is **recommended to use a native host app for testing** changes made to the editor for a more realistic experience. A demo app is included in the GutenbergKit project, along with instructions on how to use it below. +We welcome contributions! See the [Contributing Guide](./CONTRIBUTING.md) for setup instructions, development workflow, and how to submit changes. -### Demo App +## Get Involved -This demo app is useful for quickly testing changes made to the editor. - -#### iOS - -The iOS demo app loads the development server by default. - -1. Start the development server by running `make dev-server`. -1. Launch Xcode and open the `ios/Demo-iOS/Gutenberg.xcodeproj` project. -1. Select the `Gutenberg` target. -1. Run the app. - -Alternatively, you can load a production build of the web app bundled with the GutenbergKit package by running `make build` and disabling the `GUTENBERG_EDITOR_URL` environment variable by navigating to _Product_ → _Scheme_ → _Edit Scheme_ in Xcode. - -
-Example Xcode environment variable - -Example Xcode environment variable - -
- -#### Android - -The Android demo app loads the production build of the web app bundled with the GutenbergKit package by default—i.e., the output of the project's `make build` command. It can be configured to load the development server by setting a `GUTENBERG_EDITOR_URL` environment variable in the `android/local.properties` file. - -1. Start the development server by running `make dev-server`. -1. Launch Android Studio and open the `android` project. -1. Modify the `android/local.properties` file to include an environment variable named `GUTENBERG_EDITOR_URL` with the development server URL. -1. Run the app on an emulator. - -
-Example Android local.properties - -``` -GUTENBERG_EDITOR_URL=http://10.0.2.2:5173/ -``` - -
- -> [!NOTE] -> Android emulators route `http://10.0.2.2` to the host machine's IP address, allowing easy access to the development server from the emulator. For iOS simulators, the localhost URL is `http://localhost`. Appending the correct Vite development server port is required, which Vite logs when starting the server. -> -> To run the demo app on a physical device, see the [physical device setup guide](./docs/physical-device-setup.md). - -See the [architecture overview](./docs/architecture.md) for additional details regarding project organization and development tips. - -## Testing - -Important, high-level test cases are [documented](./docs/test-cases.md) for manual testing guidance. Additionally, automated tests are included in the project to ensure code quality and functionality. - -To run the JavaScript tests, run the following command in your terminal: - -```bash -make test-js -``` - -To run the Swift tests, run the following command in your terminal: - -```bash -make test-swift -``` - -To run the Android tests, run the following command in your terminal: - -```bash -make test-android -``` - -## Production - -To build GutenbergKit for production run the following command in your terminal: - -```bash -make build -``` - -Once finished, the Swift and Kotlin packages are ready to publish. Consuming iOS or Android host apps can then include the GutenbergKit package as a dependency. - -## Releases - -See the [release documentation](./docs/releases.md) for more information. +Join the conversation in the [#mobile](https://wordpress.slack.com/archives/C02RQC4LY) channel on [WordPress Slack](https://make.wordpress.org/chat/). diff --git a/docs/architecture.md b/docs/architecture.md deleted file mode 100644 index bcc267e3..00000000 --- a/docs/architecture.md +++ /dev/null @@ -1,192 +0,0 @@ -# GutenbergKit Architecture - -## Overview - -GutenbergKit is a cross-platform Gutenberg block editor implementation that bridges WordPress's web-based editor with native iOS and Android applications. The architecture consists of three main layers: - -1. **Web Layer**: React-based editor using WordPress Gutenberg packages -2. **Bridge Layer**: Bidirectional communication between web and native code -3. **Native Layer**: Platform-specific implementations (Swift for iOS, Kotlin for Android) - -## Project Structure - -``` -GutenbergKit/ -├── src/ # Web editor source code -│ ├── components/ # React components -│ │ ├── editor/ # Main editor component -│ │ ├── visual-editor/ # Visual editing interface -│ │ └── text-editor/ # HTML text editing interface -│ ├── utils/ # Utility functions -│ │ └── bridge.js # Native-to-web communication -│ └── index.js # Main editor entry point -├── ios/ # iOS Swift package -│ └── Sources/ -│ └── GutenbergKit/ -├── android/ # Android Kotlin library -│ └── Gutenberg/ -├── docs/ # Documentation -└── patches/ # Third-party package patches -``` - -## Communication Architecture - -### Web → Native Communication - -The web editor communicates with native code through platform-specific APIs: - -- **iOS**: `window.webkit.messageHandlers` -- **Android**: `window.editorDelegate` - -Common message types include: - -- Editor initialization -- Content updates -- Media uploads -- Block operations -- Error reporting - -### Native → Web Communication - -Native code executes JavaScript in the WebView to: - -- Initialize the editor with content -- Update editor settings -- Handle media selection -- Process API responses - -## Development Mode - -Development mode (`?dev_mode` query parameter) enables debugging features and bypasses certain production behaviors to simplify development and testing: - -- **Development notice is displayed** - A warning notice appears to inform developers that they're running in development mode. -- **Mock GBKit global is provided** - If the native bridge (`window.GBKit`) is not available, a mock object is automatically provided to allow the editor to load without native integration. -- **React Dev Tools integration** - The editor connects to the React Dev Tools standalone server for component inspection and debugging. See the React Dev Tools section below for setup instructions. - -Add the `?dev_mode` query parameter to the editor URL: - -``` -http://localhost:3000/?dev_mode -``` - -### React Dev Tools - -The [React Developer Tools](https://react.dev/learn/react-developer-tools) allow inspecting React components, view props and state, and debug the component tree during development. GutenbergKit supports the standalone DevTools server for both browser and native WebView debugging. - -1. Start the standalone DevTools server: - - ```bash - make dev-tools - ``` - - This opens a standalone window that will display your React component tree. - -2. Start the development server: - - ```bash - make dev-server - ``` - -3. For Android emulators only, set up port forwarding: - - ```bash - adb reverse tcp:8097 tcp:8097 - ``` - -4. Load the editor with development mode enabled: - - Browser or iOS simulator: - - ``` - http://localhost:5173/?dev_mode - ``` - - Android emulator: - - ``` - http://10.0.2.2:5173/?dev_mode - ``` - - The editor will automatically connect to the DevTools server, and your component tree will appear in the standalone window. - -## Logging Configuration - -The logger utility (`src/utils/logger.js`) supports different log levels that can be controlled via: - -- The `logLevel` editor configuration option, for controlling the client console; -- And Node.js environment variables (`LOG_LEVEL=`), for project scripts. - -The default log level is `info`. The project's demo app defaults to `debug`. Available log levels are: - -- `error`: Logs only error messages -- `warn`: Logs warnings and errors -- `info`: Logs informational messages, warnings, and errors -- `debug`: Logs detailed debugging information, informational messages, warnings, and errors - -## Plugin Support - -GutenbergKit bundles `@wordpress` modules locally for offline capability and fast load times. The editor can optionally load plugin-provided blocks and custom editor assets from a remote server when configured. - -### How Plugin Loading Works - -When the `plugins` configuration option is enabled: - -1. Core `@wordpress` packages are loaded from bundled code -2. Plugin scripts and styles are fetched from the site's editor assets endpoint -3. Custom blocks and editor extensions are registered dynamically -4. The editor integrates both core and custom functionality - -This approach provides: - -- **Offline-first**: Core editor works without network connectivity -- **Extensibility**: Supports custom blocks and plugins when connected -- **Performance**: Core packages load instantly from local bundle - -### Configuration - -Enable plugins by setting the `plugins` configuration option. The editor will fetch assets from the configured `editorAssetsEndpoint` or fall back to the default Jetpack endpoint. The demo app UI allows adding site-specific editor configurations, which enables the `plugins` configuration option. - -## Testing - -### JavaScript Testing - -- Framework: Vitest -- Test files: `*.test.{js,jsx}` -- Run tests: `make test-js` - -### Native Testing - -**iOS:** - -- XCTest framework -- Run: `make test-swift-package` - -**Android:** - -- JUnit framework -- Run: `make test-android` - -## Frequently Asked Questions - -### Why do I encounter a `GBKit global not available after timeout` error when opening the GutenbergKit editor in a browser? - -This error occurs when the editor is unable to communicate with the native bridge. This is expected when opening the editor in a browser, as the native bridge is not available. GutenbergKit is designed to be used in a native host app that provides the native bridge. The GutenbergKit project includes a demo app that can be used to test the editor. - -It is possible to circumvent this this error by adding the `?dev_mode` query parameter to the editor URL in your browser. This will bypass the native bridge requirement and allow the editor to load without the native bridge. However, some features may not work as expected when using this mode. - -### Why do I encounter an `Importing a module script failed.` error? - -This [generally indicates](https://github.com/vitejs/vite/discussions/17738) that Vite is attempting to load a cached dependency that no longer exists or is corrupted. - -Often times this is paired with a following warning in the Vite development server console that looks like this: - -``` -The file does not exist at "[path]" which is in the optimize deps directory. The dependency might be incompatible with the dep optimizer. Try adding it to `optimizeDeps.exclude`. -``` - -Usually, clearing Vite's cache resolves this issue. This can be accomplished by either: - -- Stopping the development server and restarting it via the `make dev-server-force` command to force Vite to re-bundle dependencies. -- Deleting the `node_modules/.vite` directory (or `node_modules` entirely) and restarting the development server via `make dev-server`. - -You may also need to clear your browser cache to ensure no stale files are used. diff --git a/docs/code/README.md b/docs/code/README.md new file mode 100644 index 00000000..00347351 --- /dev/null +++ b/docs/code/README.md @@ -0,0 +1,21 @@ +# Code Contributions + +This guide is for developers who want to contribute code to GutenbergKit. + +## Getting Started + +- [Getting Started](./getting-started.md) - Prerequisites, setup, and running the demo apps +- [Development Tools](./development-tools.md) - Development mode, React DevTools, and logging +- [Testing](./testing.md) - Running tests and ensuring code quality +- [Troubleshooting](./troubleshooting.md) - Common issues and solutions + +## Reference + +- [Architecture](./architecture.md) - Project structure and communication patterns +- [Plugins](./plugins.md) - Plugin loading and custom blocks +- [Preloading](./preloading.md) - Asset preloading +- [Physical Device Setup](./physical-device-setup.md) - Running on physical devices + +## Get Involved + +Have questions or want to discuss development? Join the [#mobile](https://wordpress.slack.com/archives/C02RQC4LY) channel on [WordPress Slack](https://make.wordpress.org/chat/). diff --git a/docs/code/architecture.md b/docs/code/architecture.md new file mode 100644 index 00000000..9ef10f5b --- /dev/null +++ b/docs/code/architecture.md @@ -0,0 +1,56 @@ +# GutenbergKit Architecture + +## Overview + +GutenbergKit is a cross-platform Gutenberg block editor implementation that bridges WordPress's web-based editor with native iOS and Android applications. The architecture consists of three main layers: + +1. **Web Layer**: React-based editor using WordPress Gutenberg packages +2. **Bridge Layer**: Bidirectional communication between web and native code +3. **Native Layer**: Platform-specific implementations (Swift for iOS, Kotlin for Android) + +## Project Structure + +``` +GutenbergKit/ +├── src/ # Web editor source code +│ ├── components/ # React components +│ │ ├── editor/ # Main editor component +│ │ ├── visual-editor/ # Visual editing interface +│ │ └── text-editor/ # HTML text editing interface +│ ├── utils/ # Utility functions +│ │ └── bridge.js # Native-to-web communication +│ └── index.js # Main editor entry point +├── ios/ # iOS Swift package +│ └── Sources/ +│ └── GutenbergKit/ +├── android/ # Android Kotlin library +│ └── Gutenberg/ +├── docs/ # Documentation +└── patches/ # Third-party package patches +``` + +## Communication Architecture + +### Web → Native Communication + +The web editor communicates with native code through platform-specific APIs: + +- **iOS**: `window.webkit.messageHandlers` +- **Android**: `window.editorDelegate` + +Common message types include: + +- Editor initialization +- Content updates +- Media uploads +- Block operations +- Error reporting + +### Native → Web Communication + +Native code executes JavaScript in the WebView to: + +- Initialize the editor with content +- Update editor settings +- Handle media selection +- Process API responses diff --git a/docs/code/development-tools.md b/docs/code/development-tools.md new file mode 100644 index 00000000..1be71604 --- /dev/null +++ b/docs/code/development-tools.md @@ -0,0 +1,71 @@ +# Development Tools + +This guide covers debugging tools and development features available in GutenbergKit. + +## Development Mode + +Development mode (`?dev_mode` query parameter) enables debugging features and bypasses certain production behaviors to simplify development and testing: + +- **Development notice is displayed** - A warning notice appears to inform developers that they're running in development mode. +- **Make GBKit global optional** - If the native bridge (`window.GBKit`) is not available, the editor is allowed to load without native integration, but some features may be limited. +- **React Dev Tools integration** - The editor connects to the React Dev Tools standalone server for component inspection and debugging. See the React Dev Tools section below for setup instructions. + +Add the `?dev_mode` query parameter to the editor URL: + +``` +http://localhost:3000/?dev_mode +``` + +## React Dev Tools + +The [React Developer Tools](https://react.dev/learn/react-developer-tools) allow inspecting React components, view props and state, and debug the component tree during development. GutenbergKit supports the standalone DevTools server for both browser and native WebView debugging. + +1. Start the standalone DevTools server: + + ```bash + make dev-tools + ``` + + This opens a standalone window that will display your React component tree. + +2. Start the development server: + + ```bash + make dev-server + ``` + +3. For Android emulators only, set up port forwarding: + + ```bash + adb reverse tcp:8097 tcp:8097 + ``` + +4. Load the editor with development mode enabled: + + Browser or iOS simulator: + + ``` + http://localhost:5173/?dev_mode + ``` + + Android emulator: + + ``` + http://10.0.2.2:5173/?dev_mode + ``` + + The editor will automatically connect to the DevTools server, and your component tree will appear in the standalone window. + +## Logging Configuration + +The logger utility (`src/utils/logger.js`) supports different log levels that can be controlled via: + +- The `logLevel` editor configuration option, for controlling the client console; +- And Node.js environment variables (`LOG_LEVEL=`), for project scripts. + +The default log level is `info`. The project's demo app defaults to `debug`. Available log levels are: + +- `error`: Logs only error messages +- `warn`: Logs warnings and errors +- `info`: Logs informational messages, warnings, and errors +- `debug`: Logs detailed debugging information, informational messages, warnings, and errors diff --git a/docs/code/getting-started.md b/docs/code/getting-started.md new file mode 100644 index 00000000..b93eb764 --- /dev/null +++ b/docs/code/getting-started.md @@ -0,0 +1,78 @@ +# Getting Started + +This guide will help you set up your development environment for GutenbergKit. + +## Prerequisites + +In order to build GutenbergKit, the following tools must be installed on your development machine: + +- [Node.js](https://nodejs.org/en/download/) - Required for building the web app; recommend using [Node Version Manager](https://github.com/nvm-sh/nvm). +- [Xcode](https://developer.apple.com/xcode/) - Required if building the iOS demo app. +- [Android Studio](https://developer.android.com/studio) - Required if building the Android demo app. + +## Development Commands + +To see all available development commands, run `make help` (or simply `make`) in your terminal. This will display a list of all available build, test, and development commands. + +## Web App + +Install the GutenbergKit dependencies and start the development server by running the following command in your terminal: + +```bash +make dev-server +``` + +Once finished, the web app can now be accessed in your browser by visiting the URL logged in your terminal. However, it is **recommended to use a native host app for testing** changes made to the editor for a more realistic experience. A demo app is included in the GutenbergKit project, along with instructions on how to use it below. + +## Demo App + +This demo app is useful for quickly testing changes made to the editor. + +### iOS + +The iOS demo app loads the development server by default. + +1. Start the development server by running `make dev-server`. +1. Launch Xcode and open the `ios/Demo-iOS/Gutenberg.xcodeproj` project. +1. Select the `Gutenberg` target. +1. Run the app. + +Alternatively, you can load a production build of the web app bundled with the GutenbergKit package by running `make build` and disabling the `GUTENBERG_EDITOR_URL` environment variable by navigating to _Product_ → _Scheme_ → _Edit Scheme_ in Xcode. + +
+Example Xcode environment variable + +Example Xcode environment variable + +
+ +### Android + +The Android demo app loads the production build of the web app bundled with the GutenbergKit package by default—i.e., the output of the project's `make build` command. It can be configured to load the development server by setting a `GUTENBERG_EDITOR_URL` environment variable in the `android/local.properties` file. + +1. Start the development server by running `make dev-server`. +1. Launch Android Studio and open the `android` project. +1. Modify the `android/local.properties` file to include an environment variable named `GUTENBERG_EDITOR_URL` with the development server URL. +1. Run the app on an emulator. + +
+Example Android local.properties + +``` +GUTENBERG_EDITOR_URL=http://10.0.2.2:5173/ +``` + +
+ +> [!NOTE] +> Android emulators route `http://10.0.2.2` to the host machine's IP address, allowing easy access to the development server from the emulator. For iOS simulators, the localhost URL is `http://localhost`. Appending the correct Vite development server port is required, which Vite logs when starting the server. +> +> To run the demo app on a physical device, see the [physical device setup guide](./physical-device-setup.md). + +## Production Builds + +To build GutenbergKit for production run the following command in your terminal: + +```bash +make build +``` diff --git a/docs/physical-device-setup.md b/docs/code/physical-device-setup.md similarity index 100% rename from docs/physical-device-setup.md rename to docs/code/physical-device-setup.md diff --git a/docs/code/plugins.md b/docs/code/plugins.md new file mode 100644 index 00000000..cc3c5c40 --- /dev/null +++ b/docs/code/plugins.md @@ -0,0 +1,22 @@ +# Plugin Support + +GutenbergKit bundles `@wordpress` modules locally for offline capability and fast load times. The editor can optionally load plugin-provided blocks and custom editor assets from a remote server when configured. + +## How Plugin Loading Works + +When the `plugins` configuration option is enabled: + +1. Core `@wordpress` packages are loaded from bundled code +2. Plugin scripts and styles are fetched from the site's editor assets endpoint +3. Custom blocks and editor extensions are registered dynamically +4. The editor integrates both core and custom functionality + +This approach provides: + +- **Offline-first**: Core editor works without network connectivity +- **Extensibility**: Supports custom blocks and plugins when connected +- **Performance**: Core packages load instantly from local bundle + +## Configuration + +Enable plugins by setting the `plugins` configuration option. The editor will fetch assets from the configured `editorAssetsEndpoint` or fall back to the default Jetpack endpoint. The demo app UI allows adding site-specific editor configurations, which enables the `plugins` configuration option. diff --git a/docs/preloading.md b/docs/code/preloading.md similarity index 100% rename from docs/preloading.md rename to docs/code/preloading.md diff --git a/docs/code/testing.md b/docs/code/testing.md new file mode 100644 index 00000000..77f66273 --- /dev/null +++ b/docs/code/testing.md @@ -0,0 +1,62 @@ +# Testing + +This guide covers automated testing and code quality tools in GutenbergKit. + +## Automated Tests + +Important, high-level test cases are [documented](../test-cases.md) for manual testing guidance. Additionally, automated tests are included in the project to ensure code quality and functionality. + +### JavaScript Tests + +- Framework: Vitest +- Test files: `*.test.{js,jsx}` + +To run the JavaScript tests: + +```bash +make test-js +``` + +### Swift Tests + +- Framework: Swift Testing + +To run the Swift tests: + +```bash +make test-swift-package +``` + +### Android Tests + +- Framework: JUnit + +To run the Android tests: + +```bash +make test-android +``` + +## Code Quality + +Before submitting a pull request, ensure your code passes formatting and linting checks. + +### Formatting + +Format code using Prettier: + +```bash +make format +``` + +### Linting + +Lint JavaScript code using ESLint: + +```bash +# Auto-fix linting errors +make lint-js-fix + +# Verify linting passes +make lint-js +``` diff --git a/docs/code/troubleshooting.md b/docs/code/troubleshooting.md new file mode 100644 index 00000000..300ac055 --- /dev/null +++ b/docs/code/troubleshooting.md @@ -0,0 +1,30 @@ +# Troubleshooting + +This guide covers common issues and solutions when developing GutenbergKit. + +## GBKit global not available after timeout + +**Error:** `GBKit global not available after timeout` + +This error occurs when the editor is unable to communicate with the native bridge. This is expected when opening the editor in a browser, as the native bridge is not available. GutenbergKit is designed to be used in a native host app that provides the native bridge. The GutenbergKit project includes a demo app that can be used to test the editor. + +**Solution:** Add the `?dev_mode` query parameter to the editor URL in your browser. This will bypass the native bridge requirement and allow the editor to load without the native bridge. However, some features may not work as expected when using this mode. + +## Importing a module script failed + +**Error:** `Importing a module script failed.` + +This [generally indicates](https://github.com/vitejs/vite/discussions/17738) that Vite is attempting to load a cached dependency that no longer exists or is corrupted. + +Often times this is paired with a following warning in the Vite development server console that looks like this: + +``` +The file does not exist at "[path]" which is in the optimize deps directory. The dependency might be incompatible with the dep optimizer. Try adding it to `optimizeDeps.exclude`. +``` + +**Solution:** Clear Vite's cache by either: + +- Stopping the development server and restarting it via the `make dev-server-force` command to force Vite to re-bundle dependencies. +- Deleting the `node_modules/.vite` directory (or `node_modules` entirely) and restarting the development server via `make dev-server`. + +You may also need to clear your browser cache to ensure no stale files are used. diff --git a/docs/integration.md b/docs/integration.md new file mode 100644 index 00000000..708aca17 --- /dev/null +++ b/docs/integration.md @@ -0,0 +1,293 @@ +# Integration Guide + +This guide covers how to integrate GutenbergKit into your iOS or Android app. + +## Requirements + +### iOS + +- **Platform**: iOS 17+ / macOS 14+ +- **Dependencies** (automatically resolved via Swift Package Manager): + - [SwiftSoup](https://github.com/scinfu/SwiftSoup) - HTML parsing + - [SVGView](https://github.com/exyte/SVGView) - SVG rendering for block icons + +### Android + +- **Platform**: minSdk 24 (Android 7.0), targetSdk 34 +- **Dependencies** (managed via Gradle): + - `androidx.webkit:webkit` - Enhanced WebView features + - `com.google.code.gson:gson` - JSON serialization + - `kotlinx-coroutines-android` - Async operations + +## iOS Integration + +### Adding the Package + +Add GutenbergKit as a Swift Package dependency in Xcode: + +1. Go to **File → Add Package Dependencies...** +2. Enter the GutenbergKit repository URL +3. Select the `GutenbergKit` library product + +Note: The `Package.swift` is at the repository root, not in the `ios/` directory. + +### Basic Setup + +Create an `EditorViewController` with a configuration: + +```swift +import GutenbergKit + +let configuration = EditorConfigurationBuilder( + postType: "post", + siteURL: URL(string: "https://example.com")!, + siteApiRoot: URL(string: "https://example.com/wp-json")! +) + .setTitle("My Post") + .setContent("

Hello world

") + .setAuthHeader("Bearer your-token") + .build() + +let editorViewController = EditorViewController(configuration: configuration) +editorViewController.delegate = self +``` + +### Configuration Options + +The `EditorConfigurationBuilder` provides many options for customizing the editor. See [`EditorConfiguration.swift`](../ios/Sources/GutenbergKit/Sources/Model/EditorConfiguration.swift) for all available options. + +### Implementing the Delegate + +Implement `EditorViewControllerDelegate` to handle editor events: + +```swift +extension YourViewController: EditorViewControllerDelegate { + func editorDidLoad(_ viewController: EditorViewController) { + // Editor finished loading + } + + func editor(_ viewController: EditorViewController, didUpdateContentWithState state: EditorState) { + // Content changed - state.isEmpty indicates if editor is empty + } + + func editor(_ viewController: EditorViewController, didUpdateHistoryState state: EditorState) { + // Undo/redo state changed - use state.hasUndo and state.hasRedo + } + + func editor(_ viewController: EditorViewController, didRequestMediaFromSiteMediaLibrary config: OpenMediaLibraryAction) { + // User requested media picker - present your media library UI + } + + func editor(_ viewController: EditorViewController, didEncounterCriticalError error: Error) { + // Handle critical errors + } +} +``` + +### Getting and Setting Content + +```swift +// Set content +editorViewController.setContent("

New content

") + +// Get content +let content = try await editorViewController.getContent() + +// Get title and content together +let result = try await editorViewController.getTitleAndContent() +print("Title: \(result.title), Content: \(result.content)") +``` + +### Performance Optimization + +Pre-warm the editor for faster first load: + +```swift +// Call early in your app lifecycle +EditorViewController.warmup(configuration: configuration) +``` + +For the fastest loading, pre-fetch dependencies: + +```swift +let service = EditorService(configuration: configuration) +let dependencies = try await service.prepare { progress in + print("Loading: \(progress.fractionCompleted * 100)%") +} + +// Pass dependencies for instant loading +let editorViewController = EditorViewController( + configuration: configuration, + dependencies: dependencies +) +``` + +## Android Integration + +### Adding the Library + +There are two ways to add GutenbergKit to your Android project: + +**Option 1: Maven dependency (recommended for production)** + +Add the Automattic Maven repository to your `settings.gradle.kts`: + +```kotlin +dependencyResolutionManagement { + repositories { + maven { + url = uri("https://a8c-libs.s3.amazonaws.com/android") + } + } +} +``` + +Then add the dependency to your `build.gradle.kts`: + +```kotlin +dependencies { + implementation("org.wordpress.gutenbergkit:android:") +} +``` + +**Option 2: Local module (for development)** + +Include the `android/Gutenberg/` module directly in your project. + +### Basic Setup + +Create a `GutenbergView` and start the editor: + +```kotlin +import org.wordpress.gutenberg.GutenbergView +import org.wordpress.gutenberg.EditorConfiguration + +val gutenbergView = GutenbergView(context) +gutenbergView.initializeWebView() + +val configuration = EditorConfiguration.builder() + .setTitle("My Post") + .setContent("

Hello world

") + .setPostType("post") + .setSiteURL("https://example.com") + .setSiteApiRoot("https://example.com/wp-json") + .setAuthHeader("Bearer your-token") + .build() + +gutenbergView.start(configuration) +``` + +### Configuration Options + +The `EditorConfiguration.builder()` provides many options for customizing the editor. See [`EditorConfiguration.kt`](../android/Gutenberg/src/main/java/org/wordpress/gutenberg/EditorConfiguration.kt) for all available options. + +### Setting Up Listeners + +Register listeners to handle editor events: + +```kotlin +gutenbergView.setEditorDidBecomeAvailable { view -> + // Editor finished loading +} + +gutenbergView.setContentChangeListener { + // Content changed +} + +gutenbergView.setHistoryChangeListener { hasUndo, hasRedo -> + // Undo/redo state changed +} + +gutenbergView.setOpenMediaLibraryListener { config -> + // User requested media picker + // config.allowedTypes, config.multiple, etc. +} + +gutenbergView.setLogJsExceptionListener { exception -> + // Handle JavaScript exceptions +} +``` + +### Getting and Setting Content + +```kotlin +// Set content +gutenbergView.setContent("

New content

") + +// Get title and content +gutenbergView.getTitleAndContent( + originalContent = "", + callback = object : TitleAndContentCallback { + override fun onResult(title: CharSequence, content: CharSequence) { + // Use title and content + } + }, + completeComposition = true +) +``` + +### Performance Optimization + +Pre-warm the editor for faster first load: + +```kotlin +// Call early in your app lifecycle +GutenbergView.warmup(context, configuration) +``` + +Enable asset caching for plugin and theme styles: + +```kotlin +val configuration = EditorConfiguration.builder() + .setEnableAssetCaching(true) + .setCachedAssetHosts(setOf("example.com", "cdn.example.com")) + .build() +``` + +## Common Patterns + +### Plugin Support + +Load custom blocks and editor assets from your site: + +```swift +// iOS +let configuration = EditorConfigurationBuilder(...) + .setShouldUsePlugins(true) + .setEditorAssetsEndpoint(URL(string: "https://example.com/editor-assets")!) + .build() +``` + +```kotlin +// Android +val configuration = EditorConfiguration.builder() + .setPlugins(true) + .setEditorAssetsEndpoint("https://example.com/editor-assets") + .build() +``` + +### Theme Styles + +Apply your site's theme styles to the editor. This requires valid editor settings (JSON) that provide theme style configuration (colors, typography, etc.) from your WordPress site's block editor settings endpoint (`/wp-block-editor/v1/settings`) or elsewhere. + +```swift +// iOS +// Fetch editor settings JSON from your WordPress site +let editorSettingsJSON = try await fetchEditorSettings() + +let configuration = EditorConfigurationBuilder(...) + .setShouldUseThemeStyles(true) + .setEditorSettings(editorSettingsJSON) + .build() +``` + +```kotlin +// Android +// Fetch editor settings JSON from your WordPress site +val editorSettingsJSON = fetchEditorSettings() + +val configuration = EditorConfiguration.builder() + .setThemeStyles(true) + .setEditorSettings(editorSettingsJSON) + .build() +```