chore: initial commit (Phase 3 scaffold)
Some checks are pending
ci / validate (push) Waiting to run
15
.editorconfig
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[*.{yml,yaml,json,md}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
||||||
36
.gitea/workflows/ci.yml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
name: ci
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main, master]
|
||||||
|
pull_request: {}
|
||||||
|
workflow_dispatch: {}
|
||||||
|
|
||||||
|
# We run a Linux runner; macOS xcodebuild is not available here.
|
||||||
|
# This workflow validates structure (yaml, file presence) and basic Swift.
|
||||||
|
jobs:
|
||||||
|
validate:
|
||||||
|
runs-on: cxai-hostinger
|
||||||
|
container: debian:bookworm
|
||||||
|
steps:
|
||||||
|
- name: Install deps
|
||||||
|
run: |
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install -y --no-install-recommends git ca-certificates curl python3-yaml >/dev/null
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Lint workflow YAML
|
||||||
|
run: |
|
||||||
|
python3 - <<'PY'
|
||||||
|
import sys, yaml, glob
|
||||||
|
for f in glob.glob('.gitea/workflows/*.yml') + glob.glob('.github/workflows/*.yml'):
|
||||||
|
try:
|
||||||
|
yaml.safe_load(open(f))
|
||||||
|
except Exception as e:
|
||||||
|
print(f'YAML ERROR {f}: {e}'); sys.exit(1)
|
||||||
|
print('workflows ok')
|
||||||
|
PY
|
||||||
|
- name: Project sanity
|
||||||
|
run: |
|
||||||
|
test -f README.md || (echo "missing README" && exit 1)
|
||||||
|
test -f Makefile || (echo "missing Makefile" && exit 1)
|
||||||
|
ls *.xcodeproj >/dev/null 2>&1 && echo "xcodeproj: $(ls -d *.xcodeproj)" || true
|
||||||
|
[ -f Package.swift ] && echo "Package.swift present" || true
|
||||||
27
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
name: ci
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: build (${{ matrix.os }})
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [macos-14]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Show toolchain
|
||||||
|
run: |
|
||||||
|
xcodebuild -version || true
|
||||||
|
swift --version || true
|
||||||
|
- name: Build
|
||||||
|
run: make build
|
||||||
|
- name: Test
|
||||||
|
run: make test
|
||||||
|
- name: Lint
|
||||||
|
run: make lint
|
||||||
54
.gitignore
vendored
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
|
.AppleDouble
|
||||||
|
.LSOverride
|
||||||
|
Icon?
|
||||||
|
|
||||||
|
# Xcode
|
||||||
|
build/
|
||||||
|
DerivedData/
|
||||||
|
*.xcworkspace/xcuserdata/
|
||||||
|
*.xcodeproj/xcuserdata/
|
||||||
|
*.xcodeproj/project.xcworkspace/xcuserdata/
|
||||||
|
*.xcuserstate
|
||||||
|
*.moved-aside
|
||||||
|
*.pbxuser
|
||||||
|
!default.pbxuser
|
||||||
|
*.mode1v3
|
||||||
|
!default.mode1v3
|
||||||
|
*.mode2v3
|
||||||
|
!default.mode2v3
|
||||||
|
*.perspectivev3
|
||||||
|
!default.perspectivev3
|
||||||
|
|
||||||
|
# SwiftPM
|
||||||
|
.build/
|
||||||
|
.swiftpm/xcode/
|
||||||
|
.swiftpm/configuration/
|
||||||
|
Package.resolved
|
||||||
|
|
||||||
|
# CocoaPods / Carthage
|
||||||
|
Pods/
|
||||||
|
Carthage/Build/
|
||||||
|
|
||||||
|
# fastlane
|
||||||
|
fastlane/report.xml
|
||||||
|
fastlane/Preview.html
|
||||||
|
fastlane/screenshots/**/*.png
|
||||||
|
fastlane/test_output/
|
||||||
|
|
||||||
|
# Coverage
|
||||||
|
*.gcno
|
||||||
|
*.gcda
|
||||||
|
*.profdata
|
||||||
|
*.profraw
|
||||||
|
coverage/
|
||||||
|
|
||||||
|
# Editors
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# Local
|
||||||
|
*.local
|
||||||
|
secrets.env
|
||||||
16
CHANGELOG.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented here.
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/)
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Repository scaffolding: README, LICENSE (MIT), .gitignore, Makefile,
|
||||||
|
CONTRIBUTING, SECURITY, CODEOWNERS, .editorconfig, CI workflow.
|
||||||
|
|
||||||
|
## [0.1.0] - 2026-04-22
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Initial safari-extension scaffold for CxLLM-SAFARI.
|
||||||
6
CODEOWNERS
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Default owners for everything in this repo.
|
||||||
|
* @CxAI-LLM/maintainers
|
||||||
|
|
||||||
|
# Build & CI
|
||||||
|
/.github/ @CxAI-LLM/devops
|
||||||
|
/Makefile @CxAI-LLM/devops
|
||||||
23
CONTRIBUTING.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Contributing to CxLLM-SAFARI
|
||||||
|
|
||||||
|
Thanks for taking the time to contribute!
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
1. Open an issue describing the change before sending a PR for non-trivial work.
|
||||||
|
2. Fork / branch off `main`. Use a descriptive branch name (`feat/...`, `fix/...`).
|
||||||
|
3. Keep commits scoped and use **Conventional Commits** (`feat:`, `fix:`,
|
||||||
|
`docs:`, `refactor:`, `test:`, `chore:`).
|
||||||
|
4. Run `make lint` and `make test` before pushing.
|
||||||
|
5. Open a PR — CI must pass before review.
|
||||||
|
|
||||||
|
## Coding style
|
||||||
|
|
||||||
|
- Swift: `swiftformat` defaults + `swiftlint` rules from the umbrella repo.
|
||||||
|
- Objective-C / C / C++: clang-format `-style=Google`.
|
||||||
|
- No tabs in Swift; 4-space indent in C/C++.
|
||||||
|
|
||||||
|
## Code of conduct
|
||||||
|
|
||||||
|
By contributing you agree to abide by the project's Code of Conduct
|
||||||
|
(see the umbrella `cxllm-code` repo).
|
||||||
909
CxLLM-SAFARI.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,909 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 77;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
20F2B0CE2F99764000E7D2D9 /* CxLLM-SAFARI Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 20F2B0CD2F99764000E7D2D9 /* CxLLM-SAFARI Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
|
20F2B0D82F99764000E7D2D9 /* CxLLM-SAFARI Extension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 20F2B0D72F99764000E7D2D9 /* CxLLM-SAFARI Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
20F2B0CF2F99764000E7D2D9 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 20F2B08B2F99763E00E7D2D9 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 20F2B0CC2F99764000E7D2D9;
|
||||||
|
remoteInfo = "CxLLM-SAFARI Extension (iOS)";
|
||||||
|
};
|
||||||
|
20F2B0D92F99764000E7D2D9 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 20F2B08B2F99763E00E7D2D9 /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 20F2B0D62F99764000E7D2D9;
|
||||||
|
remoteInfo = "CxLLM-SAFARI Extension (macOS)";
|
||||||
|
};
|
||||||
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
20F2B1002F99764000E7D2D9 /* Embed Foundation Extensions */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 13;
|
||||||
|
files = (
|
||||||
|
20F2B0CE2F99764000E7D2D9 /* CxLLM-SAFARI Extension.appex in Embed Foundation Extensions */,
|
||||||
|
);
|
||||||
|
name = "Embed Foundation Extensions";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
20F2B10A2F99764000E7D2D9 /* Embed Foundation Extensions */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 13;
|
||||||
|
files = (
|
||||||
|
20F2B0D82F99764000E7D2D9 /* CxLLM-SAFARI Extension.appex in Embed Foundation Extensions */,
|
||||||
|
);
|
||||||
|
name = "Embed Foundation Extensions";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXFileReference section */
|
||||||
|
20F2B0A92F99764000E7D2D9 /* CxLLM-SAFARI.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "CxLLM-SAFARI.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
20F2B0BF2F99764000E7D2D9 /* CxLLM-SAFARI.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "CxLLM-SAFARI.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
20F2B0CD2F99764000E7D2D9 /* CxLLM-SAFARI Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "CxLLM-SAFARI Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
20F2B0D72F99764000E7D2D9 /* CxLLM-SAFARI Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "CxLLM-SAFARI Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
|
20F2B0FB2F99764000E7D2D9 /* Exceptions for "Shared (App)" folder in "CxLLM-SAFARI (iOS)" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
"/Localized: Resources/Main.html",
|
||||||
|
Assets.xcassets,
|
||||||
|
Resources/Icon.png,
|
||||||
|
Resources/Script.js,
|
||||||
|
Resources/Style.css,
|
||||||
|
ViewController.m,
|
||||||
|
);
|
||||||
|
target = 20F2B0A82F99764000E7D2D9 /* CxLLM-SAFARI (iOS) */;
|
||||||
|
};
|
||||||
|
20F2B0FF2F99764000E7D2D9 /* Exceptions for "iOS (Extension)" folder in "CxLLM-SAFARI Extension (iOS)" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
Info.plist,
|
||||||
|
);
|
||||||
|
target = 20F2B0CC2F99764000E7D2D9 /* CxLLM-SAFARI Extension (iOS) */;
|
||||||
|
};
|
||||||
|
20F2B1042F99764000E7D2D9 /* Exceptions for "iOS (App)" folder in "CxLLM-SAFARI (iOS)" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
Info.plist,
|
||||||
|
);
|
||||||
|
target = 20F2B0A82F99764000E7D2D9 /* CxLLM-SAFARI (iOS) */;
|
||||||
|
};
|
||||||
|
20F2B1052F99764000E7D2D9 /* Exceptions for "Shared (App)" folder in "CxLLM-SAFARI (macOS)" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
"/Localized: Resources/Main.html",
|
||||||
|
Assets.xcassets,
|
||||||
|
Resources/Icon.png,
|
||||||
|
Resources/Script.js,
|
||||||
|
Resources/Style.css,
|
||||||
|
ViewController.m,
|
||||||
|
);
|
||||||
|
target = 20F2B0BE2F99764000E7D2D9 /* CxLLM-SAFARI (macOS) */;
|
||||||
|
};
|
||||||
|
20F2B1092F99764000E7D2D9 /* Exceptions for "macOS (Extension)" folder in "CxLLM-SAFARI Extension (macOS)" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
Info.plist,
|
||||||
|
);
|
||||||
|
target = 20F2B0D62F99764000E7D2D9 /* CxLLM-SAFARI Extension (macOS) */;
|
||||||
|
};
|
||||||
|
20F2B10E2F99764000E7D2D9 /* Exceptions for "Shared (Extension)" folder in "CxLLM-SAFARI Extension (iOS)" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
Resources/_locales,
|
||||||
|
Resources/background.js,
|
||||||
|
Resources/content.js,
|
||||||
|
Resources/images,
|
||||||
|
Resources/manifest.json,
|
||||||
|
Resources/popup.css,
|
||||||
|
Resources/popup.html,
|
||||||
|
Resources/popup.js,
|
||||||
|
SafariWebExtensionHandler.m,
|
||||||
|
);
|
||||||
|
target = 20F2B0CC2F99764000E7D2D9 /* CxLLM-SAFARI Extension (iOS) */;
|
||||||
|
};
|
||||||
|
20F2B10F2F99764000E7D2D9 /* Exceptions for "Shared (Extension)" folder in "CxLLM-SAFARI Extension (macOS)" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
Resources/_locales,
|
||||||
|
Resources/background.js,
|
||||||
|
Resources/content.js,
|
||||||
|
Resources/images,
|
||||||
|
Resources/manifest.json,
|
||||||
|
Resources/popup.css,
|
||||||
|
Resources/popup.html,
|
||||||
|
Resources/popup.js,
|
||||||
|
SafariWebExtensionHandler.m,
|
||||||
|
);
|
||||||
|
target = 20F2B0D62F99764000E7D2D9 /* CxLLM-SAFARI Extension (macOS) */;
|
||||||
|
};
|
||||||
|
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
|
|
||||||
|
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||||
|
20F2B08F2F99763E00E7D2D9 /* Shared (App) */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
20F2B0FB2F99764000E7D2D9 /* Exceptions for "Shared (App)" folder in "CxLLM-SAFARI (iOS)" target */,
|
||||||
|
20F2B1052F99764000E7D2D9 /* Exceptions for "Shared (App)" folder in "CxLLM-SAFARI (macOS)" target */,
|
||||||
|
);
|
||||||
|
path = "Shared (App)";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
20F2B0992F99764000E7D2D9 /* Shared (Extension) */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
20F2B10E2F99764000E7D2D9 /* Exceptions for "Shared (Extension)" folder in "CxLLM-SAFARI Extension (iOS)" target */,
|
||||||
|
20F2B10F2F99764000E7D2D9 /* Exceptions for "Shared (Extension)" folder in "CxLLM-SAFARI Extension (macOS)" target */,
|
||||||
|
);
|
||||||
|
explicitFolders = (
|
||||||
|
Resources/_locales,
|
||||||
|
Resources/images,
|
||||||
|
);
|
||||||
|
path = "Shared (Extension)";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
20F2B0AB2F99764000E7D2D9 /* iOS (App) */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
20F2B1042F99764000E7D2D9 /* Exceptions for "iOS (App)" folder in "CxLLM-SAFARI (iOS)" target */,
|
||||||
|
);
|
||||||
|
path = "iOS (App)";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
20F2B0C02F99764000E7D2D9 /* macOS (App) */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
path = "macOS (App)";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
20F2B0D12F99764000E7D2D9 /* iOS (Extension) */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
20F2B0FF2F99764000E7D2D9 /* Exceptions for "iOS (Extension)" folder in "CxLLM-SAFARI Extension (iOS)" target */,
|
||||||
|
);
|
||||||
|
path = "iOS (Extension)";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
20F2B0DB2F99764000E7D2D9 /* macOS (Extension) */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
20F2B1092F99764000E7D2D9 /* Exceptions for "macOS (Extension)" folder in "CxLLM-SAFARI Extension (macOS)" target */,
|
||||||
|
);
|
||||||
|
path = "macOS (Extension)";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXFileSystemSynchronizedRootGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
20F2B0A62F99764000E7D2D9 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
20F2B0BC2F99764000E7D2D9 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
20F2B0CA2F99764000E7D2D9 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
20F2B0D42F99764000E7D2D9 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
20F2B08A2F99763E00E7D2D9 = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
20F2B08F2F99763E00E7D2D9 /* Shared (App) */,
|
||||||
|
20F2B0992F99764000E7D2D9 /* Shared (Extension) */,
|
||||||
|
20F2B0AB2F99764000E7D2D9 /* iOS (App) */,
|
||||||
|
20F2B0C02F99764000E7D2D9 /* macOS (App) */,
|
||||||
|
20F2B0D12F99764000E7D2D9 /* iOS (Extension) */,
|
||||||
|
20F2B0DB2F99764000E7D2D9 /* macOS (Extension) */,
|
||||||
|
20F2B0AA2F99764000E7D2D9 /* Products */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
20F2B0AA2F99764000E7D2D9 /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
20F2B0A92F99764000E7D2D9 /* CxLLM-SAFARI.app */,
|
||||||
|
20F2B0BF2F99764000E7D2D9 /* CxLLM-SAFARI.app */,
|
||||||
|
20F2B0CD2F99764000E7D2D9 /* CxLLM-SAFARI Extension.appex */,
|
||||||
|
20F2B0D72F99764000E7D2D9 /* CxLLM-SAFARI Extension.appex */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
20F2B0A82F99764000E7D2D9 /* CxLLM-SAFARI (iOS) */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 20F2B1012F99764000E7D2D9 /* Build configuration list for PBXNativeTarget "CxLLM-SAFARI (iOS)" */;
|
||||||
|
buildPhases = (
|
||||||
|
20F2B0A52F99764000E7D2D9 /* Sources */,
|
||||||
|
20F2B0A62F99764000E7D2D9 /* Frameworks */,
|
||||||
|
20F2B0A72F99764000E7D2D9 /* Resources */,
|
||||||
|
20F2B1002F99764000E7D2D9 /* Embed Foundation Extensions */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
20F2B0D02F99764000E7D2D9 /* PBXTargetDependency */,
|
||||||
|
);
|
||||||
|
fileSystemSynchronizedGroups = (
|
||||||
|
20F2B0AB2F99764000E7D2D9 /* iOS (App) */,
|
||||||
|
);
|
||||||
|
name = "CxLLM-SAFARI (iOS)";
|
||||||
|
packageProductDependencies = (
|
||||||
|
);
|
||||||
|
productName = "CxLLM-SAFARI (iOS)";
|
||||||
|
productReference = 20F2B0A92F99764000E7D2D9 /* CxLLM-SAFARI.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
|
20F2B0BE2F99764000E7D2D9 /* CxLLM-SAFARI (macOS) */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 20F2B10B2F99764000E7D2D9 /* Build configuration list for PBXNativeTarget "CxLLM-SAFARI (macOS)" */;
|
||||||
|
buildPhases = (
|
||||||
|
20F2B0BB2F99764000E7D2D9 /* Sources */,
|
||||||
|
20F2B0BC2F99764000E7D2D9 /* Frameworks */,
|
||||||
|
20F2B0BD2F99764000E7D2D9 /* Resources */,
|
||||||
|
20F2B10A2F99764000E7D2D9 /* Embed Foundation Extensions */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
20F2B0DA2F99764000E7D2D9 /* PBXTargetDependency */,
|
||||||
|
);
|
||||||
|
fileSystemSynchronizedGroups = (
|
||||||
|
20F2B0C02F99764000E7D2D9 /* macOS (App) */,
|
||||||
|
);
|
||||||
|
name = "CxLLM-SAFARI (macOS)";
|
||||||
|
packageProductDependencies = (
|
||||||
|
);
|
||||||
|
productName = "CxLLM-SAFARI (macOS)";
|
||||||
|
productReference = 20F2B0BF2F99764000E7D2D9 /* CxLLM-SAFARI.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
|
20F2B0CC2F99764000E7D2D9 /* CxLLM-SAFARI Extension (iOS) */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 20F2B0FC2F99764000E7D2D9 /* Build configuration list for PBXNativeTarget "CxLLM-SAFARI Extension (iOS)" */;
|
||||||
|
buildPhases = (
|
||||||
|
20F2B0C92F99764000E7D2D9 /* Sources */,
|
||||||
|
20F2B0CA2F99764000E7D2D9 /* Frameworks */,
|
||||||
|
20F2B0CB2F99764000E7D2D9 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
fileSystemSynchronizedGroups = (
|
||||||
|
20F2B0D12F99764000E7D2D9 /* iOS (Extension) */,
|
||||||
|
);
|
||||||
|
name = "CxLLM-SAFARI Extension (iOS)";
|
||||||
|
packageProductDependencies = (
|
||||||
|
);
|
||||||
|
productName = "CxLLM-SAFARI Extension (iOS)";
|
||||||
|
productReference = 20F2B0CD2F99764000E7D2D9 /* CxLLM-SAFARI Extension.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
|
20F2B0D62F99764000E7D2D9 /* CxLLM-SAFARI Extension (macOS) */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 20F2B1062F99764000E7D2D9 /* Build configuration list for PBXNativeTarget "CxLLM-SAFARI Extension (macOS)" */;
|
||||||
|
buildPhases = (
|
||||||
|
20F2B0D32F99764000E7D2D9 /* Sources */,
|
||||||
|
20F2B0D42F99764000E7D2D9 /* Frameworks */,
|
||||||
|
20F2B0D52F99764000E7D2D9 /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
fileSystemSynchronizedGroups = (
|
||||||
|
20F2B0DB2F99764000E7D2D9 /* macOS (Extension) */,
|
||||||
|
);
|
||||||
|
name = "CxLLM-SAFARI Extension (macOS)";
|
||||||
|
packageProductDependencies = (
|
||||||
|
);
|
||||||
|
productName = "CxLLM-SAFARI Extension (macOS)";
|
||||||
|
productReference = 20F2B0D72F99764000E7D2D9 /* CxLLM-SAFARI Extension.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
|
/* Begin PBXProject section */
|
||||||
|
20F2B08B2F99763E00E7D2D9 /* Project object */ = {
|
||||||
|
isa = PBXProject;
|
||||||
|
attributes = {
|
||||||
|
BuildIndependentTargetsInParallel = 1;
|
||||||
|
LastUpgradeCheck = 2630;
|
||||||
|
TargetAttributes = {
|
||||||
|
20F2B0A82F99764000E7D2D9 = {
|
||||||
|
CreatedOnToolsVersion = 26.3;
|
||||||
|
};
|
||||||
|
20F2B0BE2F99764000E7D2D9 = {
|
||||||
|
CreatedOnToolsVersion = 26.3;
|
||||||
|
};
|
||||||
|
20F2B0CC2F99764000E7D2D9 = {
|
||||||
|
CreatedOnToolsVersion = 26.3;
|
||||||
|
};
|
||||||
|
20F2B0D62F99764000E7D2D9 = {
|
||||||
|
CreatedOnToolsVersion = 26.3;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
buildConfigurationList = 20F2B08E2F99763E00E7D2D9 /* Build configuration list for PBXProject "CxLLM-SAFARI" */;
|
||||||
|
developmentRegion = en;
|
||||||
|
hasScannedForEncodings = 0;
|
||||||
|
knownRegions = (
|
||||||
|
en,
|
||||||
|
Base,
|
||||||
|
);
|
||||||
|
mainGroup = 20F2B08A2F99763E00E7D2D9;
|
||||||
|
minimizedProjectReferenceProxies = 1;
|
||||||
|
preferredProjectObjectVersion = 77;
|
||||||
|
productRefGroup = 20F2B0AA2F99764000E7D2D9 /* Products */;
|
||||||
|
projectDirPath = "";
|
||||||
|
projectRoot = "";
|
||||||
|
targets = (
|
||||||
|
20F2B0A82F99764000E7D2D9 /* CxLLM-SAFARI (iOS) */,
|
||||||
|
20F2B0BE2F99764000E7D2D9 /* CxLLM-SAFARI (macOS) */,
|
||||||
|
20F2B0CC2F99764000E7D2D9 /* CxLLM-SAFARI Extension (iOS) */,
|
||||||
|
20F2B0D62F99764000E7D2D9 /* CxLLM-SAFARI Extension (macOS) */,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
/* End PBXProject section */
|
||||||
|
|
||||||
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
20F2B0A72F99764000E7D2D9 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
20F2B0BD2F99764000E7D2D9 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
20F2B0CB2F99764000E7D2D9 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
20F2B0D52F99764000E7D2D9 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
20F2B0A52F99764000E7D2D9 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
20F2B0BB2F99764000E7D2D9 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
20F2B0C92F99764000E7D2D9 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
20F2B0D32F99764000E7D2D9 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
20F2B0D02F99764000E7D2D9 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 20F2B0CC2F99764000E7D2D9 /* CxLLM-SAFARI Extension (iOS) */;
|
||||||
|
targetProxy = 20F2B0CF2F99764000E7D2D9 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
20F2B0DA2F99764000E7D2D9 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 20F2B0D62F99764000E7D2D9 /* CxLLM-SAFARI Extension (macOS) */;
|
||||||
|
targetProxy = 20F2B0D92F99764000E7D2D9 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
|
/* Begin XCBuildConfiguration section */
|
||||||
|
20F2B0FD2F99764000E7D2D9 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = DKWVC9FQJY;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "iOS (Extension)/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "CxLLM-SAFARI Extension";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "cxai-studio.CxLLM-SAFARI.Extension";
|
||||||
|
PRODUCT_NAME = "CxLLM-SAFARI Extension";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
20F2B0FE2F99764000E7D2D9 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = DKWVC9FQJY;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "iOS (Extension)/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "CxLLM-SAFARI Extension";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "cxai-studio.CxLLM-SAFARI.Extension";
|
||||||
|
PRODUCT_NAME = "CxLLM-SAFARI Extension";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
20F2B1022F99764000E7D2D9 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = DKWVC9FQJY;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "iOS (App)/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "CxLLM-SAFARI";
|
||||||
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||||
|
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
|
||||||
|
INFOPLIST_KEY_UIMainStoryboardFile = Main;
|
||||||
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
"-framework",
|
||||||
|
WebKit,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "cxai-studio.CxLLM-SAFARI";
|
||||||
|
PRODUCT_NAME = "CxLLM-SAFARI";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
20F2B1032F99764000E7D2D9 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = DKWVC9FQJY;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "iOS (App)/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "CxLLM-SAFARI";
|
||||||
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||||
|
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
|
||||||
|
INFOPLIST_KEY_UIMainStoryboardFile = Main;
|
||||||
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
|
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
"-framework",
|
||||||
|
WebKit,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "cxai-studio.CxLLM-SAFARI";
|
||||||
|
PRODUCT_NAME = "CxLLM-SAFARI";
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
20F2B1072F99764000E7D2D9 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = DKWVC9FQJY;
|
||||||
|
ENABLE_APP_SANDBOX = YES;
|
||||||
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
ENABLE_USER_SELECTED_FILES = readonly;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "macOS (Extension)/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "CxLLM-SAFARI Extension";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
"@executable_path/../../../../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "cxai-studio.CxLLM-SAFARI.Extension";
|
||||||
|
PRODUCT_NAME = "CxLLM-SAFARI Extension";
|
||||||
|
SDKROOT = macosx;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
20F2B1082F99764000E7D2D9 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = DKWVC9FQJY;
|
||||||
|
ENABLE_APP_SANDBOX = YES;
|
||||||
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
ENABLE_USER_SELECTED_FILES = readonly;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "macOS (Extension)/Info.plist";
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "CxLLM-SAFARI Extension";
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
"@executable_path/../../../../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "cxai-studio.CxLLM-SAFARI.Extension";
|
||||||
|
PRODUCT_NAME = "CxLLM-SAFARI Extension";
|
||||||
|
SDKROOT = macosx;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
20F2B10C2F99764000E7D2D9 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = DKWVC9FQJY;
|
||||||
|
ENABLE_APP_SANDBOX = YES;
|
||||||
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
|
||||||
|
ENABLE_USER_SELECTED_FILES = readonly;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "CxLLM-SAFARI";
|
||||||
|
INFOPLIST_KEY_NSMainStoryboardFile = Main;
|
||||||
|
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
"-framework",
|
||||||
|
WebKit,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "cxai-studio.CxLLM-SAFARI";
|
||||||
|
PRODUCT_NAME = "CxLLM-SAFARI";
|
||||||
|
REGISTER_APP_GROUPS = YES;
|
||||||
|
SDKROOT = macosx;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
20F2B10D2F99764000E7D2D9 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = DKWVC9FQJY;
|
||||||
|
ENABLE_APP_SANDBOX = YES;
|
||||||
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
|
||||||
|
ENABLE_USER_SELECTED_FILES = readonly;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = "CxLLM-SAFARI";
|
||||||
|
INFOPLIST_KEY_NSMainStoryboardFile = Main;
|
||||||
|
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/../Frameworks",
|
||||||
|
);
|
||||||
|
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
OTHER_LDFLAGS = (
|
||||||
|
"-framework",
|
||||||
|
SafariServices,
|
||||||
|
"-framework",
|
||||||
|
WebKit,
|
||||||
|
);
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = "cxai-studio.CxLLM-SAFARI";
|
||||||
|
PRODUCT_NAME = "CxLLM-SAFARI";
|
||||||
|
REGISTER_APP_GROUPS = YES;
|
||||||
|
SDKROOT = macosx;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
20F2B1102F99764000E7D2D9 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
|
DEVELOPMENT_TEAM = DKWVC9FQJY;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_TESTABILITY = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
"DEBUG=1",
|
||||||
|
"$(inherited)",
|
||||||
|
);
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
20F2B1112F99764000E7D2D9 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
buildSettings = {
|
||||||
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
|
DEVELOPMENT_TEAM = DKWVC9FQJY;
|
||||||
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
|
/* Begin XCConfigurationList section */
|
||||||
|
20F2B08E2F99763E00E7D2D9 /* Build configuration list for PBXProject "CxLLM-SAFARI" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
20F2B1102F99764000E7D2D9 /* Debug */,
|
||||||
|
20F2B1112F99764000E7D2D9 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
20F2B0FC2F99764000E7D2D9 /* Build configuration list for PBXNativeTarget "CxLLM-SAFARI Extension (iOS)" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
20F2B0FD2F99764000E7D2D9 /* Debug */,
|
||||||
|
20F2B0FE2F99764000E7D2D9 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
20F2B1012F99764000E7D2D9 /* Build configuration list for PBXNativeTarget "CxLLM-SAFARI (iOS)" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
20F2B1022F99764000E7D2D9 /* Debug */,
|
||||||
|
20F2B1032F99764000E7D2D9 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
20F2B1062F99764000E7D2D9 /* Build configuration list for PBXNativeTarget "CxLLM-SAFARI Extension (macOS)" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
20F2B1072F99764000E7D2D9 /* Debug */,
|
||||||
|
20F2B1082F99764000E7D2D9 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
20F2B10B2F99764000E7D2D9 /* Build configuration list for PBXNativeTarget "CxLLM-SAFARI (macOS)" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
20F2B10C2F99764000E7D2D9 /* Debug */,
|
||||||
|
20F2B10D2F99764000E7D2D9 /* Release */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
|
/* End XCConfigurationList section */
|
||||||
|
};
|
||||||
|
rootObject = 20F2B08B2F99763E00E7D2D9 /* Project object */;
|
||||||
|
}
|
||||||
7
CxLLM-SAFARI.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 CxAI-LLM
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
43
Makefile
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Makefile — common entry points for CxLLM-SAFARI
|
||||||
|
SHELL := /bin/bash
|
||||||
|
.DEFAULT_GOAL := help
|
||||||
|
|
||||||
|
PROJECT := CxLLM-SAFARI
|
||||||
|
SCHEME ?= $(PROJECT)
|
||||||
|
CONFIG ?= Debug
|
||||||
|
DERIVED ?= build
|
||||||
|
|
||||||
|
.PHONY: help build test lint clean fmt info
|
||||||
|
|
||||||
|
help: ## show this help
|
||||||
|
@grep -E '^[a-zA-Z_-]+:.*## ' $(MAKEFILE_LIST) | awk -F':.*## ' '{printf " %-12s %s\n", $$1, $$2}'
|
||||||
|
|
||||||
|
info: ## show project info
|
||||||
|
@echo "project : $(PROJECT)"
|
||||||
|
@echo "scheme : $(SCHEME)"
|
||||||
|
@echo "config : $(CONFIG)"
|
||||||
|
@echo "derived : $(DERIVED)"
|
||||||
|
|
||||||
|
build: ## xcodebuild build (skip if no .xcodeproj)
|
||||||
|
@if ls *.xcodeproj 1>/dev/null 2>&1; then \
|
||||||
|
xcodebuild -project "$(PROJECT).xcodeproj" -scheme "$(SCHEME)" -configuration "$(CONFIG)" -derivedDataPath "$(DERIVED)" build | xcbeautify || true ; \
|
||||||
|
elif [ -f Package.swift ]; then \
|
||||||
|
swift build -c $(shell echo "$(CONFIG)" | tr '[:upper:]' '[:lower:]') ; \
|
||||||
|
else echo "no buildable target" ; fi
|
||||||
|
|
||||||
|
test: ## xcodebuild test
|
||||||
|
@if ls *.xcodeproj 1>/dev/null 2>&1; then \
|
||||||
|
xcodebuild -project "$(PROJECT).xcodeproj" -scheme "$(SCHEME)" -configuration "$(CONFIG)" -derivedDataPath "$(DERIVED)" test | xcbeautify || true ; \
|
||||||
|
elif [ -f Package.swift ]; then \
|
||||||
|
swift test ; \
|
||||||
|
else echo "no testable target" ; fi
|
||||||
|
|
||||||
|
lint: ## swiftlint + swiftformat (no-op if missing)
|
||||||
|
@command -v swiftlint >/dev/null && swiftlint --quiet || echo "swiftlint not installed"
|
||||||
|
@command -v swiftformat >/dev/null && swiftformat --lint . || echo "swiftformat not installed"
|
||||||
|
|
||||||
|
fmt: ## swiftformat in-place
|
||||||
|
@command -v swiftformat >/dev/null && swiftformat . || echo "swiftformat not installed"
|
||||||
|
|
||||||
|
clean: ## remove build artifacts
|
||||||
|
rm -rf "$(DERIVED)" .build DerivedData
|
||||||
53
README.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
# CxLLM-SAFARI
|
||||||
|
|
||||||
|
> CxLLM Safari Web Extension
|
||||||
|
|
||||||
|
Safari Web Extension (iOS + macOS shared) that injects the CxLLM assistant overlay into web pages and forwards selections to the runtime.
|
||||||
|
|
||||||
|
[](https://git.cxllm-studio.com/CxAI-LLM/CxLLM-SAFARI/actions)
|
||||||
|
[](LICENSE)
|
||||||
|
[](#)
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
`CxLLM-SAFARI` is part of the **CxLLM** product family — a layered runtime that
|
||||||
|
spans Apple kernel extensions, user-space frameworks, host applications, and
|
||||||
|
spatial / web surfaces. This module focuses on **safari-extension** concerns and is
|
||||||
|
intentionally narrow so that the CxLLM monorepo can compose targets without
|
||||||
|
pulling in unrelated dependencies.
|
||||||
|
|
||||||
|
## Repository layout
|
||||||
|
|
||||||
|
- `CxLLM-SAFARI/` — primary source folder (matches the Xcode group / SwiftPM root).
|
||||||
|
- `CxLLM-SAFARI.xcodeproj` — Xcode project (where applicable).
|
||||||
|
- `Makefile` — common entry points (`build`, `test`, `lint`, `clean`).
|
||||||
|
- `.github/workflows/ci.yml` — CI pipeline (Xcode build + lint).
|
||||||
|
- `docs/` — architecture notes and ADRs.
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build (defaults to Debug for the host platform):
|
||||||
|
make build
|
||||||
|
|
||||||
|
# Run the full test suite (unit + UI where applicable):
|
||||||
|
make test
|
||||||
|
|
||||||
|
# Static analysis + format check:
|
||||||
|
make lint
|
||||||
|
```
|
||||||
|
|
||||||
|
## Versioning
|
||||||
|
|
||||||
|
This module follows [Semantic Versioning 2.0](https://semver.org/) and is
|
||||||
|
released in lock-step with the umbrella **CxLLM** product line. See
|
||||||
|
[`CHANGELOG.md`](CHANGELOG.md) for the user-facing change log.
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
Please report security issues per [`SECURITY.md`](SECURITY.md). Do **not**
|
||||||
|
open public issues for vulnerabilities.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Released under the [MIT License](LICENSE) © 2026 CxAI-LLM.
|
||||||
19
SECURITY.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Security policy for CxLLM-SAFARI
|
||||||
|
|
||||||
|
## Reporting a vulnerability
|
||||||
|
|
||||||
|
Please email **security@cxllm-studio.com** with:
|
||||||
|
|
||||||
|
- A description of the vulnerability and its impact.
|
||||||
|
- Steps to reproduce, ideally with a minimal proof-of-concept.
|
||||||
|
- The affected version(s) / commit SHAs.
|
||||||
|
|
||||||
|
We aim to acknowledge within **2 business days** and to publish a fix or
|
||||||
|
mitigation within **30 days** for high-severity issues.
|
||||||
|
|
||||||
|
Do **not** open a public Gitea / GitHub issue for vulnerabilities.
|
||||||
|
|
||||||
|
## Supported versions
|
||||||
|
|
||||||
|
Only the `main` branch and the most recent tagged release receive security
|
||||||
|
updates.
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "tinted"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "16x16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "16x16"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "32x32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "32x32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "128x128"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "128x128"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "256x256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "256x256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "512x512"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "mac",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "512x512"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
6
Shared (App)/Assets.xcassets/Contents.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
20
Shared (App)/Assets.xcassets/LargeIcon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
20
Shared (App)/Resources/Base.lproj/Main.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
<meta http-equiv="Content-Security-Policy" content="default-src 'self'">
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="../Style.css">
|
||||||
|
<script src="../Script.js" defer></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<img src="../Icon.png" width="128" height="128" alt="CxLLM-SAFARI Icon">
|
||||||
|
<p class="platform-ios">You can turn on CxLLM-SAFARI’s Safari extension in Settings.</p>
|
||||||
|
<p class="platform-mac state-unknown">You can turn on CxLLM-SAFARI’s extension in Safari Extensions preferences.</p>
|
||||||
|
<p class="platform-mac state-on">CxLLM-SAFARI’s extension is currently on. You can turn it off in Safari Extensions preferences.</p>
|
||||||
|
<p class="platform-mac state-off">CxLLM-SAFARI’s extension is currently off. You can turn it on in Safari Extensions preferences.</p>
|
||||||
|
<button class="platform-mac open-preferences">Quit and Open Safari Extensions Preferences…</button>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
Shared (App)/Resources/Icon.png
Normal file
|
After Width: | Height: | Size: 98 KiB |
24
Shared (App)/Resources/Script.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
function show(platform, enabled, useSettingsInsteadOfPreferences) {
|
||||||
|
document.body.classList.add(`platform-${platform}`);
|
||||||
|
|
||||||
|
if (useSettingsInsteadOfPreferences) {
|
||||||
|
document.getElementsByClassName('platform-mac state-on')[0].innerText = "CxLLM-SAFARI’s extension is currently on. You can turn it off in the Extensions section of Safari Settings.";
|
||||||
|
document.getElementsByClassName('platform-mac state-off')[0].innerText = "CxLLM-SAFARI’s extension is currently off. You can turn it on in the Extensions section of Safari Settings.";
|
||||||
|
document.getElementsByClassName('platform-mac state-unknown')[0].innerText = "You can turn on CxLLM-SAFARI’s extension in the Extensions section of Safari Settings.";
|
||||||
|
document.getElementsByClassName('platform-mac open-preferences')[0].innerText = "Quit and Open Safari Settings…";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof enabled === "boolean") {
|
||||||
|
document.body.classList.toggle(`state-on`, enabled);
|
||||||
|
document.body.classList.toggle(`state-off`, !enabled);
|
||||||
|
} else {
|
||||||
|
document.body.classList.remove(`state-on`);
|
||||||
|
document.body.classList.remove(`state-off`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function openPreferences() {
|
||||||
|
webkit.messageHandlers.controller.postMessage("open-preferences");
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelector("button.open-preferences").addEventListener("click", openPreferences);
|
||||||
61
Shared (App)/Resources/Style.css
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
* {
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-webkit-user-drag: none;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
color-scheme: light dark;
|
||||||
|
|
||||||
|
--spacing: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
gap: var(--spacing);
|
||||||
|
margin: 0 calc(var(--spacing) * 2);
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
font: -apple-system-short-body;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
body:not(.platform-mac, .platform-ios) :is(.platform-mac, .platform-ios) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.platform-ios .platform-mac {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.platform-mac .platform-ios {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.platform-ios .platform-mac {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body:not(.state-on, .state-off) :is(.state-on, .state-off) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.state-on :is(.state-off, .state-unknown) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.state-off :is(.state-on, .state-unknown) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
26
Shared (App)/ViewController.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// ViewController.h
|
||||||
|
// Shared (App)
|
||||||
|
//
|
||||||
|
// Created by Stephen Carter on 4/22/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <TargetConditionals.h>
|
||||||
|
|
||||||
|
#if TARGET_OS_IOS
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
typedef UIViewController PlatformViewController;
|
||||||
|
|
||||||
|
#elif TARGET_OS_OSX
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
typedef NSViewController PlatformViewController;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@interface ViewController : PlatformViewController
|
||||||
|
|
||||||
|
@end
|
||||||
76
Shared (App)/ViewController.m
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// ViewController.m
|
||||||
|
// Shared (App)
|
||||||
|
//
|
||||||
|
// Created by Stephen Carter on 4/22/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ViewController.h"
|
||||||
|
|
||||||
|
#import <WebKit/WebKit.h>
|
||||||
|
|
||||||
|
#if TARGET_OS_OSX
|
||||||
|
#import <SafariServices/SafariServices.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static NSString * const extensionBundleIdentifier = @"cxai-studio.CxLLM-SAFARI.Extension";
|
||||||
|
|
||||||
|
@interface ViewController () <WKNavigationDelegate, WKScriptMessageHandler>
|
||||||
|
|
||||||
|
@property (nonatomic) IBOutlet WKWebView *webView;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ViewController
|
||||||
|
|
||||||
|
- (void)viewDidLoad {
|
||||||
|
[super viewDidLoad];
|
||||||
|
|
||||||
|
_webView.navigationDelegate = self;
|
||||||
|
|
||||||
|
#if TARGET_OS_IOS
|
||||||
|
_webView.scrollView.scrollEnabled = NO;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
[_webView.configuration.userContentController addScriptMessageHandler:self name:@"controller"];
|
||||||
|
|
||||||
|
[_webView loadFileURL:[NSBundle.mainBundle URLForResource:@"Main" withExtension:@"html"] allowingReadAccessToURL:NSBundle.mainBundle.resourceURL];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
|
||||||
|
#if TARGET_OS_IOS
|
||||||
|
[webView evaluateJavaScript:@"show('ios')" completionHandler:nil];
|
||||||
|
#elif TARGET_OS_OSX
|
||||||
|
[webView evaluateJavaScript:@"show('mac')" completionHandler:nil];
|
||||||
|
|
||||||
|
[SFSafariExtensionManager getStateOfSafariExtensionWithIdentifier:extensionBundleIdentifier completionHandler:^(SFSafariExtensionState *state, NSError *error) {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
if (!state) {
|
||||||
|
// Insert code to inform the user something went wrong.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString *isExtensionEnabledAsString = state.isEnabled ? @"true" : @"false";
|
||||||
|
if (@available(macOS 13, *))
|
||||||
|
[webView evaluateJavaScript:[NSString stringWithFormat:@"show('mac', %@, true)", isExtensionEnabledAsString] completionHandler:nil];
|
||||||
|
else
|
||||||
|
[webView evaluateJavaScript:[NSString stringWithFormat:@"show('mac', %@, false)", isExtensionEnabledAsString] completionHandler:nil];
|
||||||
|
});
|
||||||
|
}];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
|
||||||
|
#if TARGET_OS_OSX
|
||||||
|
if (![message.body isEqualToString:@"open-preferences"])
|
||||||
|
return;
|
||||||
|
|
||||||
|
[SFSafariApplication showPreferencesForExtensionWithIdentifier:extensionBundleIdentifier completionHandler:^(NSError *error) {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
[NSApp terminate:self];
|
||||||
|
});
|
||||||
|
}];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
10
Shared (Extension)/Resources/_locales/en/messages.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"extension_name": {
|
||||||
|
"message": "CxLLM-SAFARI",
|
||||||
|
"description": "The display name for the extension."
|
||||||
|
},
|
||||||
|
"extension_description": {
|
||||||
|
"message": "This is CxLLM-SAFARI. You should tell us what your extension does here.",
|
||||||
|
"description": "Description of what the extension does."
|
||||||
|
}
|
||||||
|
}
|
||||||
6
Shared (Extension)/Resources/background.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||||
|
console.log("Received request: ", request);
|
||||||
|
|
||||||
|
if (request.greeting === "hello")
|
||||||
|
return Promise.resolve({ farewell: "goodbye" });
|
||||||
|
});
|
||||||
7
Shared (Extension)/Resources/content.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
browser.runtime.sendMessage({ greeting: "hello" }).then((response) => {
|
||||||
|
console.log("Received response: ", response);
|
||||||
|
});
|
||||||
|
|
||||||
|
browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||||
|
console.log("Received request: ", request);
|
||||||
|
});
|
||||||
BIN
Shared (Extension)/Resources/images/icon-128.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
Shared (Extension)/Resources/images/icon-256.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
Shared (Extension)/Resources/images/icon-48.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
Shared (Extension)/Resources/images/icon-512.png
Normal file
|
After Width: | Height: | Size: 128 KiB |
BIN
Shared (Extension)/Resources/images/icon-64.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
Shared (Extension)/Resources/images/icon-96.png
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
5
Shared (Extension)/Resources/images/toolbar-icon.svg
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.9375 15.9453">
|
||||||
|
<path d="M7.96875 15.9375C12.3281 15.9375 15.9375 12.3203 15.9375 7.96875C15.9375 3.60938 12.3203 0 7.96094 0C3.60938 0 0 3.60938 0 7.96875C0 12.3203 3.61719 15.9375 7.96875 15.9375ZM7.96875 14.6094C4.28125 14.6094 1.33594 11.6562 1.33594 7.96875C1.33594 4.28125 4.27344 1.32812 7.96094 1.32812C11.6484 1.32812 14.6094 4.28125 14.6094 7.96875C14.6094 11.6562 11.6562 14.6094 7.96875 14.6094Z" />
|
||||||
|
<path d="M4.53906 8.50781C4.53906 8.70312 4.69531 8.84375 4.89844 8.84375L7.54688 8.84375L6.13281 12.6406C5.94531 13.1406 6.47656 13.4141 6.80469 13.0078L11.0859 7.63281C11.1719 7.53906 11.2188 7.42969 11.2188 7.32812C11.2188 7.13281 11.0625 6.99219 10.8594 6.99219L8.21094 6.99219L9.625 3.19531C9.8125 2.69531 9.28125 2.42188 8.95312 2.82031L4.67188 8.19531C4.58594 8.29688 4.53906 8.40625 4.53906 8.50781Z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 943 B |
33
Shared (Extension)/Resources/manifest.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"manifest_version": 3,
|
||||||
|
"default_locale": "en",
|
||||||
|
|
||||||
|
"name": "__MSG_extension_name__",
|
||||||
|
"description": "__MSG_extension_description__",
|
||||||
|
"version": "1.0",
|
||||||
|
|
||||||
|
"icons": {
|
||||||
|
"48": "images/icon-48.png",
|
||||||
|
"96": "images/icon-96.png",
|
||||||
|
"128": "images/icon-128.png",
|
||||||
|
"256": "images/icon-256.png",
|
||||||
|
"512": "images/icon-512.png"
|
||||||
|
},
|
||||||
|
|
||||||
|
"background": {
|
||||||
|
"scripts": [ "background.js" ],
|
||||||
|
"type": "module"
|
||||||
|
},
|
||||||
|
|
||||||
|
"content_scripts": [{
|
||||||
|
"js": [ "content.js" ],
|
||||||
|
"matches": [ "*://example.com/*" ]
|
||||||
|
}],
|
||||||
|
|
||||||
|
"action": {
|
||||||
|
"default_popup": "popup.html",
|
||||||
|
"default_icon": "images/toolbar-icon.svg"
|
||||||
|
},
|
||||||
|
|
||||||
|
"permissions": [ ]
|
||||||
|
}
|
||||||
15
Shared (Extension)/Resources/popup.css
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
:root {
|
||||||
|
color-scheme: light dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
width: 100px;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
font-family: system-ui;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
/* Dark Mode styles go here. */
|
||||||
|
}
|
||||||
11
Shared (Extension)/Resources/popup.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<link rel="stylesheet" href="popup.css">
|
||||||
|
<script type="module" src="popup.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<strong>Hello World!</strong>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
Shared (Extension)/Resources/popup.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
console.log("Hello World!", browser);
|
||||||
12
Shared (Extension)/SafariWebExtensionHandler.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// SafariWebExtensionHandler.h
|
||||||
|
// Shared (Extension)
|
||||||
|
//
|
||||||
|
// Created by Stephen Carter on 4/22/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface SafariWebExtensionHandler : NSObject <NSExtensionRequestHandling>
|
||||||
|
|
||||||
|
@end
|
||||||
43
Shared (Extension)/SafariWebExtensionHandler.m
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
//
|
||||||
|
// SafariWebExtensionHandler.m
|
||||||
|
// Shared (Extension)
|
||||||
|
//
|
||||||
|
// Created by Stephen Carter on 4/22/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "SafariWebExtensionHandler.h"
|
||||||
|
|
||||||
|
#import <SafariServices/SafariServices.h>
|
||||||
|
|
||||||
|
@implementation SafariWebExtensionHandler
|
||||||
|
|
||||||
|
- (void)beginRequestWithExtensionContext:(NSExtensionContext *)context {
|
||||||
|
NSExtensionItem *request = context.inputItems.firstObject;
|
||||||
|
|
||||||
|
NSUUID *profile;
|
||||||
|
if (@available(iOS 17.0, macOS 14.0, *)) {
|
||||||
|
profile = request.userInfo[SFExtensionProfileKey];
|
||||||
|
} else {
|
||||||
|
profile = request.userInfo[@"profile"];
|
||||||
|
}
|
||||||
|
|
||||||
|
id message;
|
||||||
|
if (@available(iOS 15.0, macOS 11.0, *)) {
|
||||||
|
message = request.userInfo[SFExtensionMessageKey];
|
||||||
|
} else {
|
||||||
|
message = request.userInfo[@"message"];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSLog(@"Received message from browser.runtime.sendNativeMessage: %@ (profile: %@)", message, profile.UUIDString ?: @"none");
|
||||||
|
|
||||||
|
NSExtensionItem *response = [[NSExtensionItem alloc] init];
|
||||||
|
if (@available(iOS 15.0, macOS 11.0, *)) {
|
||||||
|
response.userInfo = @{ SFExtensionMessageKey: @{ @"echo": message } };
|
||||||
|
} else {
|
||||||
|
response.userInfo = @{ @"message": @{ @"echo": message } };
|
||||||
|
}
|
||||||
|
|
||||||
|
[context completeRequestReturningItems:@[ response ] completionHandler:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
24
docs/ARCHITECTURE.md
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Architecture — CxLLM-SAFARI
|
||||||
|
|
||||||
|
> CxLLM Safari Web Extension
|
||||||
|
|
||||||
|
## Goals
|
||||||
|
|
||||||
|
- Provide a focused, well-tested safari-extension surface for the CxLLM family.
|
||||||
|
- Stay deployable on its own (no monorepo coupling).
|
||||||
|
- Keep the public ABI small and explicitly versioned.
|
||||||
|
|
||||||
|
## Boundaries
|
||||||
|
|
||||||
|
```text
|
||||||
|
+----------------------+
|
||||||
|
client --> | CxLLM-SAFARI |
|
||||||
|
+----------+-----------+
|
||||||
|
|
|
||||||
|
v
|
||||||
|
CxLLM runtime / kernel
|
||||||
|
```
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
|
||||||
|
- See `docs/adr/` for Architecture Decision Records.
|
||||||
13
docs/adr/0001-record-architecture-decisions.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# 1. Record architecture decisions
|
||||||
|
|
||||||
|
## Status
|
||||||
|
Accepted
|
||||||
|
|
||||||
|
## Context
|
||||||
|
We need a lightweight, append-only log of architectural choices.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
Use Markdown ADRs in `docs/adr/`, numbered sequentially.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
Future maintainers can read the chain of decisions without spelunking PR history.
|
||||||
12
iOS (App)/AppDelegate.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate.h
|
||||||
|
// iOS (App)
|
||||||
|
//
|
||||||
|
// Created by Stephen Carter on 4/22/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||||
|
|
||||||
|
@end
|
||||||
21
iOS (App)/AppDelegate.m
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate.m
|
||||||
|
// iOS (App)
|
||||||
|
//
|
||||||
|
// Created by Stephen Carter on 4/22/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
|
@implementation AppDelegate
|
||||||
|
|
||||||
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
|
||||||
|
// Override point for customization after application launch.
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
|
||||||
|
return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
36
iOS (App)/Base.lproj/LaunchScreen.storyboard
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19085" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||||
|
<dependencies>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19082"/>
|
||||||
|
<capability name="Image references" minToolsVersion="12.0"/>
|
||||||
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--View Controller-->
|
||||||
|
<scene sceneID="EHf-IW-A2E">
|
||||||
|
<objects>
|
||||||
|
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||||
|
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6HG-Um-bch">
|
||||||
|
<rect key="frame" x="142" y="385" width="128" height="128"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
|
<imageReference key="image" image="LargeIcon"/>
|
||||||
|
</imageView>
|
||||||
|
</subviews>
|
||||||
|
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||||
|
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="53" y="375"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
<resources>
|
||||||
|
<image name="LargeIcon" width="128" height="128"/>
|
||||||
|
</resources>
|
||||||
|
</document>
|
||||||
38
iOS (App)/Base.lproj/Main.storyboard
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
|
||||||
|
<device id="retina6_1" orientation="portrait" appearance="light"/>
|
||||||
|
<dependencies>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
|
||||||
|
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--View Controller-->
|
||||||
|
<scene sceneID="tne-QT-ifu">
|
||||||
|
<objects>
|
||||||
|
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
|
||||||
|
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<wkWebView contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="RDB-ib-igF">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<wkWebViewConfiguration key="configuration">
|
||||||
|
<audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
|
||||||
|
<wkPreferences key="preferences"/>
|
||||||
|
</wkWebViewConfiguration>
|
||||||
|
</wkWebView>
|
||||||
|
</subviews>
|
||||||
|
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||||
|
</view>
|
||||||
|
<connections>
|
||||||
|
<outlet property="webView" destination="RDB-ib-igF" id="avx-RC-qRB"/>
|
||||||
|
</connections>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="53" y="375"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
||||||
25
iOS (App)/Info.plist
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?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>UIApplicationSceneManifest</key>
|
||||||
|
<dict>
|
||||||
|
<key>UIApplicationSupportsMultipleScenes</key>
|
||||||
|
<false/>
|
||||||
|
<key>UISceneConfigurations</key>
|
||||||
|
<dict>
|
||||||
|
<key>UIWindowSceneSessionRoleApplication</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>UISceneConfigurationName</key>
|
||||||
|
<string>Default Configuration</string>
|
||||||
|
<key>UISceneDelegateClassName</key>
|
||||||
|
<string>SceneDelegate</string>
|
||||||
|
<key>UISceneStoryboardFile</key>
|
||||||
|
<string>Main</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
14
iOS (App)/SceneDelegate.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// SceneDelegate.h
|
||||||
|
// iOS (App)
|
||||||
|
//
|
||||||
|
// Created by Stephen Carter on 4/22/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface SceneDelegate : UIResponder <UIWindowSceneDelegate>
|
||||||
|
|
||||||
|
@property (strong, nonatomic) UIWindow * window;
|
||||||
|
|
||||||
|
@end
|
||||||
12
iOS (App)/SceneDelegate.m
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// SceneDelegate.m
|
||||||
|
// iOS (App)
|
||||||
|
//
|
||||||
|
// Created by Stephen Carter on 4/22/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "SceneDelegate.h"
|
||||||
|
|
||||||
|
@implementation SceneDelegate
|
||||||
|
|
||||||
|
@end
|
||||||
18
iOS (App)/main.m
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// main.m
|
||||||
|
// iOS (App)
|
||||||
|
//
|
||||||
|
// Created by Stephen Carter on 4/22/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
|
int main(int argc, char * argv[]) {
|
||||||
|
NSString *appDelegateClassName;
|
||||||
|
@autoreleasepool {
|
||||||
|
// Setup code that might create autoreleased objects goes here.
|
||||||
|
appDelegateClassName = NSStringFromClass([AppDelegate class]);
|
||||||
|
}
|
||||||
|
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
|
||||||
|
}
|
||||||
13
iOS (Extension)/Info.plist
Normal file
@ -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>SafariWebExtensionHandler</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
12
macOS (App)/AppDelegate.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate.h
|
||||||
|
// macOS (App)
|
||||||
|
//
|
||||||
|
// Created by Stephen Carter on 4/22/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||||
|
|
||||||
|
@end
|
||||||
20
macOS (App)/AppDelegate.m
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate.m
|
||||||
|
// macOS (App)
|
||||||
|
//
|
||||||
|
// Created by Stephen Carter on 4/22/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
|
@implementation AppDelegate
|
||||||
|
|
||||||
|
- (void)applicationDidFinishLaunching:(NSNotification *)notification {
|
||||||
|
// Override point for customization after application launch.
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
124
macOS (App)/Base.lproj/Main.storyboard
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="19085" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="B8D-0N-5wS">
|
||||||
|
<dependencies>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="19085"/>
|
||||||
|
<plugIn identifier="com.apple.WebKit2IBPlugin" version="19085"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--Application-->
|
||||||
|
<scene sceneID="JPo-4y-FX3">
|
||||||
|
<objects>
|
||||||
|
<application id="hnw-xV-0zn" sceneMemberID="viewController">
|
||||||
|
<menu key="mainMenu" title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||||
|
<items>
|
||||||
|
<menuItem title="CxLLM-SAFARI" id="1Xt-HY-uBw">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<menu key="submenu" title="CxLLM-SAFARI" systemMenu="apple" id="uQy-DD-JDr">
|
||||||
|
<items>
|
||||||
|
<menuItem title="About CxLLM-SAFARI" id="5kV-Vb-QxS">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="orderFrontStandardAboutPanel:" target="Ady-hI-5gd" id="Exp-CZ-Vem"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem isSeparatorItem="YES" id="VOq-y0-SEH"/>
|
||||||
|
<menuItem title="Hide CxLLM-SAFARI" keyEquivalent="h" id="Olw-nP-bQN">
|
||||||
|
<connections>
|
||||||
|
<action selector="hide:" target="Ady-hI-5gd" id="PnN-Uc-m68"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem title="Hide Others" keyEquivalent="h" id="Vdr-fp-XzO">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="hideOtherApplications:" target="Ady-hI-5gd" id="VT4-aY-XCT"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem title="Show All" id="Kd2-mp-pUS">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="unhideAllApplications:" target="Ady-hI-5gd" id="Dhg-Le-xox"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem isSeparatorItem="YES" id="kCx-OE-vgT"/>
|
||||||
|
<menuItem title="Quit CxLLM-SAFARI" keyEquivalent="q" id="4sb-4s-VLi">
|
||||||
|
<connections>
|
||||||
|
<action selector="terminate:" target="Ady-hI-5gd" id="Te7-pn-YzF"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
</items>
|
||||||
|
</menu>
|
||||||
|
</menuItem>
|
||||||
|
<menuItem title="Help" id="wpr-3q-Mcd">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<menu key="submenu" title="Help" systemMenu="help" id="F2S-fz-NVQ">
|
||||||
|
<items>
|
||||||
|
<menuItem title="CxLLM-SAFARI Help" keyEquivalent="?" id="FKE-Sm-Kum">
|
||||||
|
<connections>
|
||||||
|
<action selector="showHelp:" target="Ady-hI-5gd" id="y7X-2Q-9no"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
|
</items>
|
||||||
|
</menu>
|
||||||
|
</menuItem>
|
||||||
|
</items>
|
||||||
|
</menu>
|
||||||
|
<connections>
|
||||||
|
<outlet property="delegate" destination="Voe-Tx-rLC" id="PrD-fu-P6m"/>
|
||||||
|
</connections>
|
||||||
|
</application>
|
||||||
|
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModuleProvider=""/>
|
||||||
|
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||||
|
<customObject id="Ady-hI-5gd" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="76" y="-134"/>
|
||||||
|
</scene>
|
||||||
|
<!--Window Controller-->
|
||||||
|
<scene sceneID="R2V-B0-nI4">
|
||||||
|
<objects>
|
||||||
|
<windowController showSeguePresentationStyle="single" id="B8D-0N-5wS" sceneMemberID="viewController">
|
||||||
|
<window key="window" title="CxLLM-SAFARI" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" releasedWhenClosed="NO" animationBehavior="default" id="IQv-IB-iLA">
|
||||||
|
<windowStyleMask key="styleMask" titled="YES" closable="YES"/>
|
||||||
|
<windowCollectionBehavior key="collectionBehavior" fullScreenNone="YES"/>
|
||||||
|
<rect key="contentRect" x="196" y="240" width="425" height="325"/>
|
||||||
|
<rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
|
||||||
|
<connections>
|
||||||
|
<outlet property="delegate" destination="B8D-0N-5wS" id="98r-iN-zZc"/>
|
||||||
|
</connections>
|
||||||
|
</window>
|
||||||
|
<connections>
|
||||||
|
<segue destination="XfG-lQ-9wD" kind="relationship" relationship="window.shadowedContentViewController" id="cq2-FE-JQM"/>
|
||||||
|
</connections>
|
||||||
|
</windowController>
|
||||||
|
<customObject id="Oky-zY-oP4" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="75" y="250"/>
|
||||||
|
</scene>
|
||||||
|
<!--View Controller-->
|
||||||
|
<scene sceneID="hIz-AP-VOD">
|
||||||
|
<objects>
|
||||||
|
<viewController id="XfG-lQ-9wD" customClass="ViewController" customModuleProvider="" sceneMemberID="viewController">
|
||||||
|
<view key="view" id="m2S-Jp-Qdl">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="425" height="325"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<subviews>
|
||||||
|
<wkWebView wantsLayer="YES" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eOr-cG-IQY">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="425" height="325"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<wkWebViewConfiguration key="configuration">
|
||||||
|
<audiovisualMediaTypes key="mediaTypesRequiringUserActionForPlayback" none="YES"/>
|
||||||
|
<wkPreferences key="preferences"/>
|
||||||
|
</wkWebViewConfiguration>
|
||||||
|
</wkWebView>
|
||||||
|
</subviews>
|
||||||
|
</view>
|
||||||
|
<connections>
|
||||||
|
<outlet property="webView" destination="eOr-cG-IQY" id="GFe-mU-dBY"/>
|
||||||
|
</connections>
|
||||||
|
</viewController>
|
||||||
|
<customObject id="rPt-NT-nkU" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="75" y="655"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
||||||
15
macOS (App)/main.m
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// main.m
|
||||||
|
// macOS (App)
|
||||||
|
//
|
||||||
|
// Created by Stephen Carter on 4/22/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
int main(int argc, const char * argv[]) {
|
||||||
|
@autoreleasepool {
|
||||||
|
// Setup code that might create autoreleased objects goes here.
|
||||||
|
}
|
||||||
|
return NSApplicationMain(argc, argv);
|
||||||
|
}
|
||||||
13
macOS (Extension)/Info.plist
Normal file
@ -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>SafariWebExtensionHandler</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||