Skip to content

Commit

Permalink
feat(@lexical/devtools): Added full Safari support
Browse files Browse the repository at this point in the history
  • Loading branch information
StyleT committed May 14, 2024
1 parent ec18fcf commit 1ab6dd7
Show file tree
Hide file tree
Showing 34 changed files with 1,214 additions and 44 deletions.
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
**/dist/**
**/build/**
**/npm/**
**/.output/**
**/.browser-profiles/**
**/__tests__/integration/fixtures/**
packages/**/.wxt/**
packages/playwright
Expand Down
76 changes: 38 additions & 38 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions packages/lexical-devtools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,23 @@ $ npm run dev
- WXT Framework debugging: `DEBUG_WXT=1 npm run dev`
- If you detach the Dev Tools in a separate window, and press `Cmd+Option+I` while Dev Tools window is focused, you will invoke the Dev Tools for the Dev Tools window.

**Safari:**

To develop and run Safari version of the extension you (obviously) need a Mac and Xcode installed. Safari on the contrary to other browsers doesn't accept web extensions as a zip archive but rather requires you to [wrap it in native code (Swift) wrapper](https://developer.apple.com/documentation/safariservices/safari_web_extensions/converting_a_web_extension_for_safari/). Fortunately this process is mostly automated here.

```bash
# Install Xcode

# Environment setup
sudo xcode-select -s /Applications/Xcode.app
xcodebuild --install
sudo xcodebuild -license
xcodebuild -runFirstLaunch

# Normal operation
npm run dev:safari
```

## Design

This extension follows typical [Browser DevTools architecture](https://developer.chrome.com/docs/extensions/how-to/devtools/extend-devtools) that includes sereral independent contexts that communicate via events or extension APIs.
Expand Down
9 changes: 5 additions & 4 deletions packages/lexical-devtools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"dev": "wxt",
"dev:firefox": "wxt -b firefox",
"dev:edge": "wxt -b edge",
"dev:safari": "xcrun safari-web-extension-converter --macos-only --no-prompt .output/safari-mv2",
"dev:safari": "npm run build:safari -- --mode development && xcodebuild -configuration Debug -scheme Lexical\\ Developer\\ Tools -project ./safari-xcode//Lexical\\ Developer\\ Tools/Lexical\\ Developer\\ Tools.xcodeproj && echo \"Open Safari, allow unsigned extensions in developer settings, enable extension in extensions manager (if needed)\"",
"safari:convert": "xcrun safari-web-extension-converter --app-name 'Lexical Developer Tools' --project-location ./safari-xcode --macos-only --no-prompt --force --no-open .output/safari-mv2",
"build": "npm-run-all build:chrome build:firefox build:edge build:safari",
"build:chrome": "wxt build -b chrome",
"build:firefox": "wxt build -b firefox",
Expand All @@ -27,9 +28,9 @@
"@chakra-ui/react": "^2.8.2",
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@webext-pegasus/rpc": "^0.0.4",
"@webext-pegasus/store-zustand": "^0.0.4",
"@webext-pegasus/transport": "^0.0.4",
"@webext-pegasus/rpc": "^0.2.0",
"@webext-pegasus/store-zustand": "^0.2.0",
"@webext-pegasus/transport": "^0.2.0",
"framer-motion": "^11.1.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
7 changes: 7 additions & 0 deletions packages/lexical-devtools/safari-xcode/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
xcuserdata/
*.xcworkspace
build/
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSExtension</key>
<dict>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.Safari.web-extension</string>
<key>NSExtensionPrincipalClass</key>
<string>$(PRODUCT_MODULE_NAME).SafariWebExtensionHandler</string>
</dict>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// SafariWebExtensionHandler.swift
// Lexical Developer Tools Extension
//
// Created by Vladlen Fedosov on 5/14/24.
//

import SafariServices
import os.log

class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {

func beginRequest(with context: NSExtensionContext) {
let request = context.inputItems.first as? NSExtensionItem

let profile: UUID?
if #available(iOS 17.0, macOS 14.0, *) {
profile = request?.userInfo?[SFExtensionProfileKey] as? UUID
} else {
profile = request?.userInfo?["profile"] as? UUID
}

let message: Any?
if #available(iOS 17.0, macOS 14.0, *) {
message = request?.userInfo?[SFExtensionMessageKey]
} else {
message = request?.userInfo?["message"]
}

os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@ (profile: %@)", String(describing: message), profile?.uuidString ?? "none")

let response = NSExtensionItem()
response.userInfo = [ SFExtensionMessageKey: [ "echo": message ] ]

context.completeRequest(returningItems: [ response ], completionHandler: nil)
}

}
Loading

0 comments on commit 1ab6dd7

Please sign in to comment.