├── .assets ├── installation.png └── usage.gif ├── .github ├── FUNDING.yml └── workflows │ ├── build.yml │ └── homebrew.yml ├── .gitignore ├── .swift-version ├── .swiftformat ├── ActionExtension ├── ActionExtension.entitlements ├── ActionRequestHandler.swift ├── Info.plist └── Media.xcassets │ ├── Contents.json │ ├── Symbol.symbolset │ ├── Contents.json │ └── doc.badge.gearshape.svg │ └── TouchBarBezel.colorset │ └── Contents.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── SourceEditorExtension ├── GenDiagramInBrowser.swift ├── Info.plist ├── PreferencesCommand.swift ├── SourceEditorExtension.entitlements └── SourceEditorExtension.swift ├── SwiftPlantUMLApp.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ └── Package.resolved └── xcshareddata │ └── xcschemes │ ├── SourceEditorExtension.xcscheme │ └── SwiftPlantUMLApp.xcscheme ├── SwiftPlantUMLApp ├── AppDelegate.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── 1024.png │ │ ├── 128.png │ │ ├── 16.png │ │ ├── 256.png │ │ ├── 32.png │ │ ├── 512.png │ │ ├── 64.png │ │ └── Contents.json │ ├── Color.colorset │ │ └── Contents.json │ ├── Contents.json │ ├── Logo.imageset │ │ ├── 128.png │ │ ├── 256.png │ │ ├── 64.png │ │ └── Contents.json │ └── appstore.png ├── Base.lproj │ └── Main.storyboard ├── ContentView.swift ├── Info.plist ├── Preview Content │ └── Preview Assets.xcassets │ │ └── Contents.json ├── SettingsView.swift ├── Shared │ ├── SettingsModel.swift │ └── Utils.swift ├── SwiftPlantUMLApp.entitlements ├── SwiftPlantUMLAppApp.swift ├── ThemeView.swift └── ViewController.swift └── XPCService ├── Info.plist ├── XPCService.entitlements ├── XPCService.swift ├── XPCServiceProtocol.swift └── main.swift /.assets/installation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/29539e2bd6a45f2e399bb2bcfa0c6f5899481895/.assets/installation.png -------------------------------------------------------------------------------- /.assets/usage.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/29539e2bd6a45f2e399bb2bcfa0c6f5899481895/.assets/usage.gif -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [marcoeidinger] 2 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - dev 8 | pull_request: 9 | branches: 10 | - '*' 11 | 12 | jobs: 13 | build: 14 | 15 | runs-on: macos-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Build 20 | run: xcodebuild -scheme SwiftPlantUMLApp -sdk macosx CODE_SIGN_IDENTITY="" clean build 21 | -------------------------------------------------------------------------------- /.github/workflows/homebrew.yml: -------------------------------------------------------------------------------- 1 | name: Homebrew Bump Formula 2 | on: 3 | release: 4 | types: [published] 5 | workflow_dispatch: 6 | 7 | jobs: 8 | homebrew: 9 | runs-on: macos-latest 10 | steps: 11 | - uses: macauley/action-homebrew-bump-cask@v1 12 | with: 13 | token: ${{ secrets.HOMEBREW_GITHUB_API_TOKEN }} 14 | cask: swiftplantumlapp 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## User settings 6 | xcuserdata/ 7 | 8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 9 | *.xcscmblueprint 10 | *.xccheckout 11 | 12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 13 | build/ 14 | DerivedData/ 15 | *.moved-aside 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | 28 | ## App packaging 29 | *.ipa 30 | *.dSYM.zip 31 | *.dSYM 32 | 33 | ## Playgrounds 34 | timeline.xctimeline 35 | playground.xcworkspace 36 | 37 | # Swift Package Manager 38 | # 39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 40 | # Packages/ 41 | # Package.pins 42 | # Package.resolved 43 | # *.xcodeproj 44 | # 45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 46 | # hence it is not needed unless you have added a package configuration file to your project 47 | # .swiftpm 48 | 49 | .build/ 50 | 51 | # CocoaPods 52 | # 53 | # We recommend against adding the Pods directory to your .gitignore. However 54 | # you should judge for yourself, the pros and cons are mentioned at: 55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 56 | # 57 | # Pods/ 58 | # 59 | # Add this line if you want to avoid checking in source code from the Xcode workspace 60 | # *.xcworkspace 61 | 62 | # Carthage 63 | # 64 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 65 | # Carthage/Checkouts 66 | 67 | Carthage/Build/ 68 | 69 | # Accio dependency management 70 | Dependencies/ 71 | .accio/ 72 | 73 | # fastlane 74 | # 75 | # It is recommended to not store the screenshots in the git repo. 76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 77 | # For more information about the recommended setup visit: 78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 79 | 80 | fastlane/report.xml 81 | fastlane/Preview.html 82 | fastlane/screenshots/**/*.png 83 | fastlane/test_output 84 | 85 | # Code Injection 86 | # 87 | # After new code Injection tools there's a generated folder /iOSInjectionProject 88 | # https://github.com/johnno1962/injectionforxcode 89 | 90 | iOSInjectionProject/ 91 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 5.3 2 | -------------------------------------------------------------------------------- /.swiftformat: -------------------------------------------------------------------------------- 1 | --header strip -------------------------------------------------------------------------------- /ActionExtension/ActionExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ActionExtension/ActionRequestHandler.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XPCService 3 | 4 | class ActionRequestHandler: NSObject, NSExtensionRequestHandling { 5 | lazy var connection: NSXPCConnection = { 6 | let connection = NSXPCConnection(serviceName: "us.eidinger.SwiftPlantUMLXPCService") 7 | connection.remoteObjectInterface = NSXPCInterface(with: XPCServiceProtocol.self) 8 | connection.resume() 9 | return connection 10 | }() 11 | 12 | deinit { 13 | connection.invalidate() 14 | } 15 | 16 | func beginRequest(with context: NSExtensionContext) { 17 | // For an Action Extension there will only ever be one extension item. 18 | precondition(context.inputItems.count == 1) 19 | guard let inputItem = context.inputItems[0] as? NSExtensionItem 20 | else { preconditionFailure("Expected an extension item") } 21 | 22 | // The extension item's attachments hold the set of files to process. 23 | guard let inputAttachments = inputItem.attachments 24 | else { preconditionFailure("Expected a valid array of attachments") } 25 | precondition(inputAttachments.isEmpty == false, "Expected at least one attachment") 26 | 27 | // The output of this extension is the existing swift files 28 | guard let inputAttachments = inputItem.attachments 29 | else { preconditionFailure("Expected a valid array of attachments") } 30 | 31 | let handler: (Error) -> Void = { error in 32 | print("remote proxy error: \(error)") 33 | } 34 | let service = connection.remoteObjectProxyWithErrorHandler(handler) as! XPCServiceProtocol 35 | var paths: [String] = [] 36 | 37 | // Use a dispatch group to synchronise asynchronous calls to loadInPlaceFileRepresentation. 38 | let dispatchGroup = DispatchGroup() 39 | 40 | for attachment in inputAttachments { 41 | dispatchGroup.enter() 42 | 43 | attachment.loadInPlaceFileRepresentation(forTypeIdentifier: "public.swift-source") { url, _, _ in 44 | if let url = url { 45 | paths.append(url.path) 46 | } 47 | 48 | dispatchGroup.leave() 49 | } 50 | } 51 | 52 | dispatchGroup.notify(queue: DispatchQueue.main) { 53 | service.generateDiagram(for: paths) { 54 | context.completeRequest(returningItems: [inputItem], completionHandler: nil) 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ActionExtension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIconFile 6 | 7 | NSExtension 8 | 9 | NSExtensionAttributes 10 | 11 | NSExtensionActivationRule 12 | SUBQUERY ( 13 | extensionItems, 14 | $extensionItem, 15 | SUBQUERY ( 16 | $extensionItem.attachments, 17 | $attachment, 18 | ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.swift-source" 19 | ).@count == $extensionItem.attachments.@count 20 | ).@count == 1 21 | NSExtensionServiceAllowsFinderPreviewItem 22 | 23 | NSExtensionServiceAllowsTouchBarItem 24 | 25 | NSExtensionServiceFinderPreviewIconName 26 | Symbol 27 | NSExtensionServiceRoleType 28 | NSExtensionServiceRoleTypeEditor 29 | NSExtensionServiceTouchBarBezelColorName 30 | TouchBarBezel 31 | NSExtensionServiceTouchBarIconName 32 | Symbol 33 | 34 | NSExtensionPointIdentifier 35 | com.apple.services 36 | NSExtensionPrincipalClass 37 | $(PRODUCT_MODULE_NAME).ActionRequestHandler 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /ActionExtension/Media.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ActionExtension/Media.xcassets/Symbol.symbolset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | }, 6 | "symbols" : [ 7 | { 8 | "filename" : "doc.badge.gearshape.svg", 9 | "idiom" : "universal" 10 | }, 11 | { 12 | "appearances" : [ 13 | { 14 | "appearance" : "luminosity", 15 | "value" : "light" 16 | } 17 | ], 18 | "idiom" : "universal" 19 | }, 20 | { 21 | "appearances" : [ 22 | { 23 | "appearance" : "luminosity", 24 | "value" : "dark" 25 | } 26 | ], 27 | "idiom" : "universal" 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /ActionExtension/Media.xcassets/Symbol.symbolset/doc.badge.gearshape.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | Weight/Scale Variations 18 | Ultralight 19 | Thin 20 | Light 21 | Regular 22 | Medium 23 | Semibold 24 | Bold 25 | Heavy 26 | Black 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | Design Variations 38 | Symbols are supported in up to nine weights and three scales. 39 | For optimal layout with text and other symbols, vertically align 40 | symbols with the adjacent text. 41 | 42 | 43 | 44 | 45 | 46 | Margins 47 | Leading and trailing margins on the left and right side of each symbol 48 | can be adjusted by modifying the x-location of the margin guidelines. 49 | Modifications are automatically applied proportionally to all 50 | scales and weights. 51 | 52 | 53 | 54 | Exporting 55 | Symbols should be outlined when exporting to ensure the 56 | design is preserved when submitting to Xcode. 57 | Template v.3.0 58 | Requires Xcode 13 or greater 59 | Generated from doc.badge.gearshape 60 | Typeset at 100 points 61 | Small 62 | Medium 63 | Large 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /ActionExtension/Media.xcassets/TouchBarBezel.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | }, 6 | "colors" : [ 7 | { 8 | "idiom" : "universal", 9 | "color" : { 10 | "reference" : "systemPurpleColor" 11 | } 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # [1.6.0](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/releases/tag/1.6.0) 2 | 3 | ## Features 4 | 5 | - support `package` access level ([SE-0386](https://github.com/apple/swift-evolution/blob/main/proposals/0386-package-access-modifier.md)) introduced in Swift 5.9 6 | 7 | ## Internal Dependencies 8 | 9 | uses [SwiftPlantUML@0.8.0](https://github.com/MarcoEidinger/SwiftPlantUML/releases/tag/0.8.0) 10 | 11 | # [1.5.1](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/releases/tag/1.5.1) 12 | 13 | ## Bug Fixes 14 | 15 | - Cannot define nested types in extensions and cannot extend nested types ([Issue #26](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/issues/26)) 16 | 17 | # [1.5.0](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/releases/tag/1.5.0) 18 | 19 | ## Features 20 | 21 | - Select one or more Swift files in your finder and then use a quick action to view a class diagram in your browser. 22 | 23 | Finder Action 24 | 25 | 26 | # [1.4.1](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/releases/tag/1.4.1) 27 | 28 | ## Bug Fixes 29 | 30 | - Fix previous installation error `“SwiftPlantUMLApp” is damaged and can’t be opened. You should move it to the Bin.` ([Issue #20](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/issues/20)) 31 | 32 | # [1.4.0](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/releases/tag/1.4.0) 33 | 34 | ## Features 35 | 36 | - [X] Able to merge extensions into main type. 37 | 38 | merged_extensions 39 | 40 | - [X] Able to choose a theme 41 | 42 | theme_sketchy_outline 43 | 44 | ## Improvements 45 | 46 | - [X] Show Nested Types 47 | 48 | nestedTypes 49 | - [X] Several Bug Fixes 50 | 51 | ## Internal Dependencies 52 | 53 | uses [SwiftPlantUML@0.7.0](https://github.com/MarcoEidinger/SwiftPlantUML/releases/tag/0.7.0) 54 | 55 | # [1.3.0](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/releases/tag/1.3.0) 56 | 57 | ## Features 58 | 59 | - [X] Able to set preferences to influence which code shall be considered for diagram generation. 60 | 61 | Preferences - Elements 62 | 63 | Preferences - Members 64 | 65 | Preferences - Others 66 | 67 | ## Improvements 68 | 69 | - [X] New Look & Feel (incl. logo) 70 | 71 | SwiftPlantUML user interface 72 | 73 | ## Internal Dependencies 74 | 75 | uses [SwiftPlantUML@0.6.0](https://github.com/MarcoEidinger/SwiftPlantUML/releases/tag/0.6.0) 76 | 77 | # [1.2.2](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/releases/tag/1.2.2) 78 | 79 | ## Improvements 80 | 81 | - [X] Faster launch of diagram in browser (also no longer that pesky leading `.` in the diagram textual description). 82 | 83 | ## Internal Dependencies 84 | 85 | uses [SwiftPlantUML@0.6.0](https://github.com/MarcoEidinger/SwiftPlantUML/releases/tag/0.6.0) 86 | 87 | # [1.2.1](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/releases/tag/1.2.1) 88 | 89 | ## Bug Fixes 90 | 91 | - [X] Diagram in browser will open correctly as invalid prefix `type=png&plantuml=` in script was removed. 92 | 93 | ## Internal Dependencies 94 | 95 | uses [SwiftPlantUML@0.5.2](https://github.com/MarcoEidinger/SwiftPlantUML/releases/tag/0.5.2) 96 | 97 | # [1.2.0](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/releases/tag/1.2.0) 98 | 99 | ## Features 100 | 101 | - [X] 👀 `Open` elements and members will now be rendered while this was 102 | previously not the case. 103 | - [X] ⬆️ Change of order for elements and their inheritance/extensions relationships. 104 | - before: subclass points down to superclass 105 | - now: superclass on top and subclass points up to superclass 106 | 107 | ## Internal Dependencies 108 | 109 | uses [SwiftPlantUML@0.5.0](https://github.com/MarcoEidinger/SwiftPlantUML/releases/tag/0.5.0) 110 | 111 | # [1.1.0](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/releases/tag/1.1.0) 112 | 113 | ## Features 114 | 115 | - [X] 🖥️ Use on macOS 10.15.7 and not only on macOS 11 116 | 117 | ## Internal Dependencies 118 | 119 | uses [SwiftPlantUML@0.4.0](https://github.com/MarcoEidinger/SwiftPlantUML/releases/tag/0.4.0) 120 | 121 | # [1.0.0](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/releases/tag/1.0.0) 122 | 123 | ## Features 124 | 125 | - [X] 📊 Create class diagram from Swift file 126 | - [X] 🔦 Create class diagram from selected Swift code 127 | 128 | ## Internal Dependencies 129 | 130 | uses [SwiftPlantUML@0.2.0](https://github.com/MarcoEidinger/SwiftPlantUML/releases/tag/0.2.0) 131 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 MarcoEidinger 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | SwiftPlantUML 3 |

4 | 5 | ![Build](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/workflows/Build/badge.svg) 6 | [![Swift 5.3](https://img.shields.io/badge/swift-5.3-orange.svg?style=flat)](#) 7 | [![Twitter](https://img.shields.io/badge/twitter-@MarcoEidinger-blue.svg)](http://twitter.com/MarcoEidinger) 8 | # SwiftPlantUML.app 9 | 10 | Generate and view a class diagram for Swift code in Xcode or from the Finder. 11 | 12 | Use the hosting macOS application to configure the diagram visualization. 13 | 14 | The Source Editor Extension (as well as the Action extension) makes use of [`SwiftPlantUML`](https://github.com/MarcoEidinger/SwiftPlantUML) Swift package. 15 | 16 | To generate a large diagram from a project with Swift files across folders then I recommend using `SwiftPlantUML` as a command-line tool. 17 | 18 | ## Features 19 | 20 | ### Xcode 21 | - [X] 📊 Create class diagram from Swift file 22 | - [X] 🔦 Create class diagram from selected Swift code 23 | 24 | ![SwiftPlantUML Xcode Extension - Usage Demo](.assets/usage.gif) 25 | 26 | ### Finder 27 | - [X] 📊 Create class diagram from selected Swift file(s) 28 | 29 | https://user-images.githubusercontent.com/4176826/218329052-b03ec650-d845-46a2-a31b-6d3817add52a.mp4 30 | 31 | ## Example 32 | 33 | ![SwiftPlantUML Xcode Extension - Usage Demo](.assets/usage.gif) 34 | 35 | ## Install 36 | 37 | Homebrew 38 | 39 | ```bash 40 | brew install swiftplantumlapp 41 | ``` 42 | 43 | Installation through Homebrew 44 | 45 | *Alternative* 46 | - Download latest *SwiftPlantUML* package from the [Releases](https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/releases). 47 | - Copy *SwiftPlantUML* to your *Applications* folder. 48 | 49 | ## Enable Extension 50 | - Launch *SwiftPlantUML*. 51 | 52 | SwiftPlantUML user interface 53 | 54 | - To use in **Xcode**: enable extension in System Preferences > Extensions > Xcode Source Editor > select SwiftPlantUML 55 | 56 | ![SwiftPlantUML Xcode Extension - Installation](.assets/installation.png) 57 | 58 | - To use in **Finder**: enable extension in System Preferences > Extensions > Finder > select Open Swift Class Diagram 59 | 60 | ![SwiftPlantUML Xcode Extension - Installation](.assets/installation.png) 61 | 62 | ## Configure 63 | 64 | *Optional*: 65 | 66 | Preferences - Elements 67 | 68 | Preferences - Members 69 | 70 | Preferences - Others 71 | 72 | ## Troubleshooting 73 | 74 | ### The command "Open editable diagram in browser" is still busy 75 | 76 | Xcode Source Code Extension initialization might take up ~ 30 seconds on initial launch. 77 | 78 | If the prompt does not appear within 60 seconds 79 | 80 | ![image](https://user-images.githubusercontent.com/37135317/118424310-f77dd000-b701-11eb-9b59-cd3c964e1885.png) 81 | 82 | then check for a crash report related to XPC service in Console app of your MacOS. 83 | 84 | CrashReportXPCServiceExample 85 | 86 | If you see such crash report related to `fatal error: Loading sourcekitd.framework/Versions/A/sourcekitd failed` please check the installation path of Xcode. If it's installed under `/Applications/Xcode.app`, please run: 87 | 88 | ``` 89 | sudo xcode-select -s /Applications/Xcode.app/Contents/Developer 90 | ``` 91 | 92 | If it's installed elsewhere, please replace the `/Applications/Xcode.app` path in the command above with the location where you've installed Xcode. 93 | 94 | 95 | ## Technical Details 96 | 97 | This Source Editor Extension makes use of XPC service to run the app sandboxed and use `SwiftPlantUML` (and its dependency `SourceKitten`). Source Editor Extensions using `SourceKitten` (either directly or indirectly) have to either run in a non-sandboxed app (and could not be distributed via the App Store) or use XPC service to outsource the use of `SourceKitten` to a different process. 98 | 99 | # Acknowledgements 100 | 101 | These awesome blog posts helped me to dive into Xcode Source Editor Extensions and XPC services 102 | 103 | - https://www.vadimbulavin.com/xcode-source-editor-extension-tutorial/ 104 | - https://nshipster.com/xcode-source-extensions/ 105 | - https://ilya.puchka.me/xcode-source-editor-extension-superpowered-with-sourcekitten/ 106 | - https://www.objc.io/issues/14-mac/xpc/ 107 | -------------------------------------------------------------------------------- /SourceEditorExtension/GenDiagramInBrowser.swift: -------------------------------------------------------------------------------- 1 | import ApplicationServices 2 | import Foundation 3 | import XcodeKit 4 | 5 | class GenDiagramInBrowser: NSObject, XCSourceEditorCommand { 6 | lazy var connection: NSXPCConnection = { 7 | let connection = NSXPCConnection(serviceName: "us.eidinger.SwiftPlantUMLXPCService") 8 | connection.remoteObjectInterface = NSXPCInterface(with: XPCServiceProtocol.self) 9 | connection.resume() 10 | return connection 11 | }() 12 | 13 | deinit { 14 | connection.invalidate() 15 | } 16 | 17 | func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) { 18 | let handler: (Error) -> Void = { error in 19 | print("remote proxy error: \(error)") 20 | } 21 | let service = connection.remoteObjectProxyWithErrorHandler(handler) as! XPCServiceProtocol 22 | 23 | let code = determineRelevantCodeForDiagram(invocation: invocation) 24 | 25 | service.generateDiagram(from: code) { 26 | completionHandler(nil) 27 | } 28 | } 29 | 30 | func determineRelevantCodeForDiagram(invocation: XCSourceEditorCommandInvocation) -> String { 31 | // 1. all lines of current source file in editor 32 | var code = invocation.buffer.completeBuffer 33 | // 2. check if specific lines were selected 34 | var selectedCode = "" 35 | if invocation.buffer.selections.count > 0 { 36 | for sel in invocation.buffer.selections { 37 | guard let selection = sel as? XCSourceTextRange else { continue } 38 | guard selection.start.line != selection.end.line else { continue } 39 | let selectedText = (selection.start.line ..< selection.end.line).map { invocation.buffer.lines[$0] as? String }.compactMap { $0 }.joined() 40 | if selectedText.count > 0 { 41 | selectedCode += selectedText 42 | } 43 | } 44 | if selectedCode.count > 0 { 45 | code = selectedCode 46 | } 47 | } 48 | return code 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /SourceEditorExtension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | SwiftPlantUML 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | SwiftPlantUML 17 | CFBundlePackageType 18 | XPC! 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSExtension 26 | 27 | NSExtensionAttributes 28 | 29 | XCSourceEditorCommandDefinitions 30 | 31 | 32 | XCSourceEditorCommandClassName 33 | $(PRODUCT_MODULE_NAME).GenDiagramInBrowser 34 | XCSourceEditorCommandIdentifier 35 | $(PRODUCT_BUNDLE_IDENTIFIER).GenDiagramInBrowser 36 | XCSourceEditorCommandName 37 | Open editable diagram in browser 38 | 39 | 40 | XCSourceEditorCommandClassName 41 | $(PRODUCT_MODULE_NAME).PreferencesCommand 42 | XCSourceEditorCommandIdentifier 43 | $(PRODUCT_MODULE_NAME).PreferencesCommand 44 | XCSourceEditorCommandName 45 | Preferences 46 | 47 | 48 | XCSourceEditorExtensionPrincipalClass 49 | $(PRODUCT_MODULE_NAME).SourceEditorExtension 50 | 51 | NSExtensionPointIdentifier 52 | com.apple.dt.Xcode.extension.source-editor 53 | 54 | NSHumanReadableCopyright 55 | Copyright © 2021-2024 Marco Eidinger. All rights reserved. 56 | 57 | 58 | -------------------------------------------------------------------------------- /SourceEditorExtension/PreferencesCommand.swift: -------------------------------------------------------------------------------- 1 | import AppKit 2 | import XcodeKit 3 | 4 | class PreferencesCommand: NSObject, XCSourceEditorCommand { 5 | func perform(with _: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void) { 6 | NSWorkspace.shared.open(URL(string: "swiftplantumlapp://preferences")!) 7 | completionHandler(nil) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /SourceEditorExtension/SourceEditorExtension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /SourceEditorExtension/SourceEditorExtension.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import XcodeKit 3 | 4 | class SourceEditorExtension: NSObject, XCSourceEditorExtension { 5 | /* 6 | func extensionDidFinishLaunching() { 7 | // If your extension needs to do any work at launch, implement this optional method. 8 | } 9 | */ 10 | 11 | /* 12 | var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: Any]] { 13 | // If your extension needs to return a collection of command definitions that differs from those in its Info.plist, implement this optional property getter. 14 | return [] 15 | } 16 | */ 17 | } 18 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 53; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1919C9C8296B48EA00804361 /* SwiftPlantUMLFramework in Frameworks */ = {isa = PBXBuildFile; productRef = 1919C9C7296B48EA00804361 /* SwiftPlantUMLFramework */; }; 11 | 1919C9CA296B48FC00804361 /* SwiftPlantUMLFramework in Frameworks */ = {isa = PBXBuildFile; productRef = 1919C9C9296B48FC00804361 /* SwiftPlantUMLFramework */; }; 12 | 192CDFCF2971F5F400CF914F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A73D8E225CAE9AA008DDEA3 /* Cocoa.framework */; }; 13 | 192CDFD22971F5F400CF914F /* Media.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 192CDFD12971F5F400CF914F /* Media.xcassets */; }; 14 | 192CDFD62971F5F400CF914F /* ActionRequestHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 192CDFD52971F5F400CF914F /* ActionRequestHandler.swift */; }; 15 | 192CDFDB2971F5F400CF914F /* ActionExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 192CDFCE2971F5F400CF914F /* ActionExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 16 | 192CDFE02971F60B00CF914F /* XPCService.xpc in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8A73D8FA25CAE9DD008DDEA3 /* XPCService.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 17 | 192CDFE52971F6DB00CF914F /* XPCServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A73D91825CAEA8F008DDEA3 /* XPCServiceProtocol.swift */; }; 18 | 19E902A029737244002212BA /* SwiftPlantUMLFramework in Frameworks */ = {isa = PBXBuildFile; productRef = 19E9029F29737244002212BA /* SwiftPlantUMLFramework */; }; 19 | 8A1EFEF42735DEC000BD6F69 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1EFEF32735DEC000BD6F69 /* Utils.swift */; }; 20 | 8A30356F279BA55700042D19 /* PreferencesCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A30356E279BA55700042D19 /* PreferencesCommand.swift */; }; 21 | 8A319170261911B900540446 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A31916F261911B900540446 /* AppDelegate.swift */; }; 22 | 8A3191742619123F00540446 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A3191732619123F00540446 /* ViewController.swift */; }; 23 | 8A3191792619124B00540446 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8A3191772619124B00540446 /* Main.storyboard */; }; 24 | 8A42F198279B6B95003BCDB4 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A42F197279B6B95003BCDB4 /* SettingsView.swift */; }; 25 | 8A73D8CC25CAE974008DDEA3 /* SwiftPlantUMLAppApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A73D8CB25CAE974008DDEA3 /* SwiftPlantUMLAppApp.swift */; }; 26 | 8A73D8CE25CAE974008DDEA3 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A73D8CD25CAE974008DDEA3 /* ContentView.swift */; }; 27 | 8A73D8D025CAE978008DDEA3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A73D8CF25CAE978008DDEA3 /* Assets.xcassets */; }; 28 | 8A73D8D325CAE978008DDEA3 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8A73D8D225CAE978008DDEA3 /* Preview Assets.xcassets */; }; 29 | 8A73D8E325CAE9AA008DDEA3 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A73D8E225CAE9AA008DDEA3 /* Cocoa.framework */; }; 30 | 8A73D8E825CAE9AA008DDEA3 /* SourceEditorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A73D8E725CAE9AA008DDEA3 /* SourceEditorExtension.swift */; }; 31 | 8A73D8EA25CAE9AA008DDEA3 /* GenDiagramInBrowser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A73D8E925CAE9AA008DDEA3 /* GenDiagramInBrowser.swift */; }; 32 | 8A73D8EF25CAE9AA008DDEA3 /* SourceEditorExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 8A73D8E025CAE9AA008DDEA3 /* SourceEditorExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 33 | 8A73D90525CAE9DD008DDEA3 /* XPCService.xpc in Embed XPC Services */ = {isa = PBXBuildFile; fileRef = 8A73D8FA25CAE9DD008DDEA3 /* XPCService.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 34 | 8A73D91425CAEA78008DDEA3 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A73D91325CAEA78008DDEA3 /* main.swift */; }; 35 | 8A73D91925CAEA8F008DDEA3 /* XPCServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A73D91825CAEA8F008DDEA3 /* XPCServiceProtocol.swift */; }; 36 | 8A73D91E25CAEA9E008DDEA3 /* XPCService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A73D91D25CAEA9E008DDEA3 /* XPCService.swift */; }; 37 | 8A73D92825CAEB4F008DDEA3 /* XPCService.xpc in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8A73D8FA25CAE9DD008DDEA3 /* XPCService.xpc */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 38 | 8A9E73BF25CAEBAF00327AD1 /* XPCServiceProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A73D91825CAEA8F008DDEA3 /* XPCServiceProtocol.swift */; }; 39 | 8A9E73CA25CAEE2B00327AD1 /* XcodeKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8A73D8E425CAE9AA008DDEA3 /* XcodeKit.framework */; }; 40 | 8A9E73CB25CAEE2B00327AD1 /* XcodeKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 8A73D8E425CAE9AA008DDEA3 /* XcodeKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 41 | 8A9F8E68273ED22700D29025 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A1EFEF32735DEC000BD6F69 /* Utils.swift */; }; 42 | 8A9F8E6E273EECF300D29025 /* SettingsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A9F8E6D273EECF300D29025 /* SettingsModel.swift */; }; 43 | 8A9F8E6F273EECF300D29025 /* SettingsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A9F8E6D273EECF300D29025 /* SettingsModel.swift */; }; 44 | /* End PBXBuildFile section */ 45 | 46 | /* Begin PBXContainerItemProxy section */ 47 | 192CDFD92971F5F400CF914F /* PBXContainerItemProxy */ = { 48 | isa = PBXContainerItemProxy; 49 | containerPortal = 8A73D8C025CAE974008DDEA3 /* Project object */; 50 | proxyType = 1; 51 | remoteGlobalIDString = 192CDFCD2971F5F400CF914F; 52 | remoteInfo = ActionExtension; 53 | }; 54 | 192CDFE32971F68700CF914F /* PBXContainerItemProxy */ = { 55 | isa = PBXContainerItemProxy; 56 | containerPortal = 8A73D8C025CAE974008DDEA3 /* Project object */; 57 | proxyType = 1; 58 | remoteGlobalIDString = 8A73D8F925CAE9DD008DDEA3; 59 | remoteInfo = XPCService; 60 | }; 61 | 8A73D8ED25CAE9AA008DDEA3 /* PBXContainerItemProxy */ = { 62 | isa = PBXContainerItemProxy; 63 | containerPortal = 8A73D8C025CAE974008DDEA3 /* Project object */; 64 | proxyType = 1; 65 | remoteGlobalIDString = 8A73D8DF25CAE9AA008DDEA3; 66 | remoteInfo = SourceEditorExtension; 67 | }; 68 | 8A73D90325CAE9DD008DDEA3 /* PBXContainerItemProxy */ = { 69 | isa = PBXContainerItemProxy; 70 | containerPortal = 8A73D8C025CAE974008DDEA3 /* Project object */; 71 | proxyType = 1; 72 | remoteGlobalIDString = 8A73D8F925CAE9DD008DDEA3; 73 | remoteInfo = XPCService; 74 | }; 75 | 8A73D92525CAEB2B008DDEA3 /* PBXContainerItemProxy */ = { 76 | isa = PBXContainerItemProxy; 77 | containerPortal = 8A73D8C025CAE974008DDEA3 /* Project object */; 78 | proxyType = 1; 79 | remoteGlobalIDString = 8A73D8F925CAE9DD008DDEA3; 80 | remoteInfo = XPCService; 81 | }; 82 | /* End PBXContainerItemProxy section */ 83 | 84 | /* Begin PBXCopyFilesBuildPhase section */ 85 | 192CDFDF2971F5FF00CF914F /* CopyFiles */ = { 86 | isa = PBXCopyFilesBuildPhase; 87 | buildActionMask = 2147483647; 88 | dstPath = "$(CONTENTS_FOLDER_PATH)/XPCServices"; 89 | dstSubfolderSpec = 16; 90 | files = ( 91 | 192CDFE02971F60B00CF914F /* XPCService.xpc in CopyFiles */, 92 | ); 93 | runOnlyForDeploymentPostprocessing = 0; 94 | }; 95 | 8A73D8F325CAE9AA008DDEA3 /* Embed Foundation Extensions */ = { 96 | isa = PBXCopyFilesBuildPhase; 97 | buildActionMask = 2147483647; 98 | dstPath = ""; 99 | dstSubfolderSpec = 13; 100 | files = ( 101 | 192CDFDB2971F5F400CF914F /* ActionExtension.appex in Embed Foundation Extensions */, 102 | 8A73D8EF25CAE9AA008DDEA3 /* SourceEditorExtension.appex in Embed Foundation Extensions */, 103 | ); 104 | name = "Embed Foundation Extensions"; 105 | runOnlyForDeploymentPostprocessing = 0; 106 | }; 107 | 8A73D90925CAE9DD008DDEA3 /* Embed XPC Services */ = { 108 | isa = PBXCopyFilesBuildPhase; 109 | buildActionMask = 2147483647; 110 | dstPath = "$(CONTENTS_FOLDER_PATH)/XPCServices"; 111 | dstSubfolderSpec = 16; 112 | files = ( 113 | 8A73D90525CAE9DD008DDEA3 /* XPCService.xpc in Embed XPC Services */, 114 | ); 115 | name = "Embed XPC Services"; 116 | runOnlyForDeploymentPostprocessing = 0; 117 | }; 118 | 8A73D92725CAEB3B008DDEA3 /* CopyFiles */ = { 119 | isa = PBXCopyFilesBuildPhase; 120 | buildActionMask = 2147483647; 121 | dstPath = "$(CONTENTS_FOLDER_PATH)/XPCServices"; 122 | dstSubfolderSpec = 16; 123 | files = ( 124 | 8A73D92825CAEB4F008DDEA3 /* XPCService.xpc in CopyFiles */, 125 | ); 126 | runOnlyForDeploymentPostprocessing = 0; 127 | }; 128 | 8A9E73CC25CAEE2B00327AD1 /* Embed Frameworks */ = { 129 | isa = PBXCopyFilesBuildPhase; 130 | buildActionMask = 2147483647; 131 | dstPath = ""; 132 | dstSubfolderSpec = 10; 133 | files = ( 134 | 8A9E73CB25CAEE2B00327AD1 /* XcodeKit.framework in Embed Frameworks */, 135 | ); 136 | name = "Embed Frameworks"; 137 | runOnlyForDeploymentPostprocessing = 0; 138 | }; 139 | /* End PBXCopyFilesBuildPhase section */ 140 | 141 | /* Begin PBXFileReference section */ 142 | 192CDFCE2971F5F400CF914F /* ActionExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ActionExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 143 | 192CDFD12971F5F400CF914F /* Media.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Media.xcassets; sourceTree = ""; }; 144 | 192CDFD52971F5F400CF914F /* ActionRequestHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionRequestHandler.swift; sourceTree = ""; }; 145 | 192CDFD72971F5F400CF914F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 146 | 192CDFD82971F5F400CF914F /* ActionExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ActionExtension.entitlements; sourceTree = ""; }; 147 | 8A1EFEF32735DEC000BD6F69 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; 148 | 8A30356E279BA55700042D19 /* PreferencesCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesCommand.swift; sourceTree = ""; }; 149 | 8A31916F261911B900540446 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 150 | 8A3191732619123F00540446 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 151 | 8A3191782619124B00540446 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 152 | 8A42F197279B6B95003BCDB4 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; 153 | 8A73D8C825CAE974008DDEA3 /* SwiftPlantUMLApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftPlantUMLApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 154 | 8A73D8CB25CAE974008DDEA3 /* SwiftPlantUMLAppApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftPlantUMLAppApp.swift; sourceTree = ""; }; 155 | 8A73D8CD25CAE974008DDEA3 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 156 | 8A73D8CF25CAE978008DDEA3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 157 | 8A73D8D225CAE978008DDEA3 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 158 | 8A73D8D425CAE978008DDEA3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 159 | 8A73D8D525CAE978008DDEA3 /* SwiftPlantUMLApp.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SwiftPlantUMLApp.entitlements; sourceTree = ""; }; 160 | 8A73D8E025CAE9AA008DDEA3 /* SourceEditorExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SourceEditorExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 161 | 8A73D8E225CAE9AA008DDEA3 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 162 | 8A73D8E425CAE9AA008DDEA3 /* XcodeKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XcodeKit.framework; path = Library/Frameworks/XcodeKit.framework; sourceTree = DEVELOPER_DIR; }; 163 | 8A73D8E725CAE9AA008DDEA3 /* SourceEditorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SourceEditorExtension.swift; sourceTree = ""; }; 164 | 8A73D8E925CAE9AA008DDEA3 /* GenDiagramInBrowser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenDiagramInBrowser.swift; sourceTree = ""; }; 165 | 8A73D8EB25CAE9AA008DDEA3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 166 | 8A73D8EC25CAE9AA008DDEA3 /* SourceEditorExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SourceEditorExtension.entitlements; sourceTree = ""; }; 167 | 8A73D8FA25CAE9DD008DDEA3 /* XPCService.xpc */ = {isa = PBXFileReference; explicitFileType = "wrapper.xpc-service"; includeInIndex = 0; path = XPCService.xpc; sourceTree = BUILT_PRODUCTS_DIR; }; 168 | 8A73D90225CAE9DD008DDEA3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 169 | 8A73D91325CAEA78008DDEA3 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 170 | 8A73D91825CAEA8F008DDEA3 /* XPCServiceProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XPCServiceProtocol.swift; sourceTree = ""; }; 171 | 8A73D91D25CAEA9E008DDEA3 /* XPCService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XPCService.swift; sourceTree = ""; }; 172 | 8A9F8E69273ED6D300D29025 /* XPCService.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = XPCService.entitlements; sourceTree = ""; }; 173 | 8A9F8E6D273EECF300D29025 /* SettingsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsModel.swift; sourceTree = ""; }; 174 | /* End PBXFileReference section */ 175 | 176 | /* Begin PBXFrameworksBuildPhase section */ 177 | 192CDFCB2971F5F400CF914F /* Frameworks */ = { 178 | isa = PBXFrameworksBuildPhase; 179 | buildActionMask = 2147483647; 180 | files = ( 181 | 19E902A029737244002212BA /* SwiftPlantUMLFramework in Frameworks */, 182 | 192CDFCF2971F5F400CF914F /* Cocoa.framework in Frameworks */, 183 | ); 184 | runOnlyForDeploymentPostprocessing = 0; 185 | }; 186 | 8A73D8C525CAE974008DDEA3 /* Frameworks */ = { 187 | isa = PBXFrameworksBuildPhase; 188 | buildActionMask = 2147483647; 189 | files = ( 190 | 1919C9C8296B48EA00804361 /* SwiftPlantUMLFramework in Frameworks */, 191 | ); 192 | runOnlyForDeploymentPostprocessing = 0; 193 | }; 194 | 8A73D8DD25CAE9AA008DDEA3 /* Frameworks */ = { 195 | isa = PBXFrameworksBuildPhase; 196 | buildActionMask = 2147483647; 197 | files = ( 198 | 8A73D8E325CAE9AA008DDEA3 /* Cocoa.framework in Frameworks */, 199 | 8A9E73CA25CAEE2B00327AD1 /* XcodeKit.framework in Frameworks */, 200 | ); 201 | runOnlyForDeploymentPostprocessing = 0; 202 | }; 203 | 8A73D8F725CAE9DD008DDEA3 /* Frameworks */ = { 204 | isa = PBXFrameworksBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | 1919C9CA296B48FC00804361 /* SwiftPlantUMLFramework in Frameworks */, 208 | ); 209 | runOnlyForDeploymentPostprocessing = 0; 210 | }; 211 | /* End PBXFrameworksBuildPhase section */ 212 | 213 | /* Begin PBXGroup section */ 214 | 192CDFD02971F5F400CF914F /* ActionExtension */ = { 215 | isa = PBXGroup; 216 | children = ( 217 | 192CDFD12971F5F400CF914F /* Media.xcassets */, 218 | 192CDFD52971F5F400CF914F /* ActionRequestHandler.swift */, 219 | 192CDFD72971F5F400CF914F /* Info.plist */, 220 | 192CDFD82971F5F400CF914F /* ActionExtension.entitlements */, 221 | ); 222 | path = ActionExtension; 223 | sourceTree = ""; 224 | }; 225 | 8A73D8BF25CAE974008DDEA3 = { 226 | isa = PBXGroup; 227 | children = ( 228 | 8A73D8CA25CAE974008DDEA3 /* SwiftPlantUMLApp */, 229 | 8A73D8E625CAE9AA008DDEA3 /* SourceEditorExtension */, 230 | 8A73D8FB25CAE9DD008DDEA3 /* XPCService */, 231 | 192CDFD02971F5F400CF914F /* ActionExtension */, 232 | 8A73D8E125CAE9AA008DDEA3 /* Frameworks */, 233 | 8A73D8C925CAE974008DDEA3 /* Products */, 234 | ); 235 | sourceTree = ""; 236 | }; 237 | 8A73D8C925CAE974008DDEA3 /* Products */ = { 238 | isa = PBXGroup; 239 | children = ( 240 | 8A73D8C825CAE974008DDEA3 /* SwiftPlantUMLApp.app */, 241 | 8A73D8E025CAE9AA008DDEA3 /* SourceEditorExtension.appex */, 242 | 8A73D8FA25CAE9DD008DDEA3 /* XPCService.xpc */, 243 | 192CDFCE2971F5F400CF914F /* ActionExtension.appex */, 244 | ); 245 | name = Products; 246 | sourceTree = ""; 247 | }; 248 | 8A73D8CA25CAE974008DDEA3 /* SwiftPlantUMLApp */ = { 249 | isa = PBXGroup; 250 | children = ( 251 | 8A31916F261911B900540446 /* AppDelegate.swift */, 252 | 8A3191732619123F00540446 /* ViewController.swift */, 253 | 8A3191772619124B00540446 /* Main.storyboard */, 254 | 8A73D8CB25CAE974008DDEA3 /* SwiftPlantUMLAppApp.swift */, 255 | 8A73D8CD25CAE974008DDEA3 /* ContentView.swift */, 256 | 8A42F197279B6B95003BCDB4 /* SettingsView.swift */, 257 | 8A9F8E6A273EECBC00D29025 /* Shared */, 258 | 8A73D8CF25CAE978008DDEA3 /* Assets.xcassets */, 259 | 8A73D8D425CAE978008DDEA3 /* Info.plist */, 260 | 8A73D8D525CAE978008DDEA3 /* SwiftPlantUMLApp.entitlements */, 261 | 8A73D8D125CAE978008DDEA3 /* Preview Content */, 262 | ); 263 | path = SwiftPlantUMLApp; 264 | sourceTree = ""; 265 | }; 266 | 8A73D8D125CAE978008DDEA3 /* Preview Content */ = { 267 | isa = PBXGroup; 268 | children = ( 269 | 8A73D8D225CAE978008DDEA3 /* Preview Assets.xcassets */, 270 | ); 271 | path = "Preview Content"; 272 | sourceTree = ""; 273 | }; 274 | 8A73D8E125CAE9AA008DDEA3 /* Frameworks */ = { 275 | isa = PBXGroup; 276 | children = ( 277 | 8A73D8E225CAE9AA008DDEA3 /* Cocoa.framework */, 278 | 8A73D8E425CAE9AA008DDEA3 /* XcodeKit.framework */, 279 | ); 280 | name = Frameworks; 281 | sourceTree = ""; 282 | }; 283 | 8A73D8E625CAE9AA008DDEA3 /* SourceEditorExtension */ = { 284 | isa = PBXGroup; 285 | children = ( 286 | 8A73D8E725CAE9AA008DDEA3 /* SourceEditorExtension.swift */, 287 | 8A73D8E925CAE9AA008DDEA3 /* GenDiagramInBrowser.swift */, 288 | 8A73D8EB25CAE9AA008DDEA3 /* Info.plist */, 289 | 8A73D8EC25CAE9AA008DDEA3 /* SourceEditorExtension.entitlements */, 290 | 8A30356E279BA55700042D19 /* PreferencesCommand.swift */, 291 | ); 292 | path = SourceEditorExtension; 293 | sourceTree = ""; 294 | }; 295 | 8A73D8FB25CAE9DD008DDEA3 /* XPCService */ = { 296 | isa = PBXGroup; 297 | children = ( 298 | 8A9F8E69273ED6D300D29025 /* XPCService.entitlements */, 299 | 8A73D90225CAE9DD008DDEA3 /* Info.plist */, 300 | 8A73D91325CAEA78008DDEA3 /* main.swift */, 301 | 8A73D91825CAEA8F008DDEA3 /* XPCServiceProtocol.swift */, 302 | 8A73D91D25CAEA9E008DDEA3 /* XPCService.swift */, 303 | ); 304 | path = XPCService; 305 | sourceTree = ""; 306 | }; 307 | 8A9F8E6A273EECBC00D29025 /* Shared */ = { 308 | isa = PBXGroup; 309 | children = ( 310 | 8A9F8E6D273EECF300D29025 /* SettingsModel.swift */, 311 | 8A1EFEF32735DEC000BD6F69 /* Utils.swift */, 312 | ); 313 | path = Shared; 314 | sourceTree = ""; 315 | }; 316 | /* End PBXGroup section */ 317 | 318 | /* Begin PBXNativeTarget section */ 319 | 192CDFCD2971F5F400CF914F /* ActionExtension */ = { 320 | isa = PBXNativeTarget; 321 | buildConfigurationList = 192CDFDE2971F5F400CF914F /* Build configuration list for PBXNativeTarget "ActionExtension" */; 322 | buildPhases = ( 323 | 192CDFCA2971F5F400CF914F /* Sources */, 324 | 192CDFCB2971F5F400CF914F /* Frameworks */, 325 | 192CDFCC2971F5F400CF914F /* Resources */, 326 | 192CDFDF2971F5FF00CF914F /* CopyFiles */, 327 | ); 328 | buildRules = ( 329 | ); 330 | dependencies = ( 331 | 192CDFE42971F68700CF914F /* PBXTargetDependency */, 332 | ); 333 | name = ActionExtension; 334 | packageProductDependencies = ( 335 | 19E9029F29737244002212BA /* SwiftPlantUMLFramework */, 336 | ); 337 | productName = ActionExtension; 338 | productReference = 192CDFCE2971F5F400CF914F /* ActionExtension.appex */; 339 | productType = "com.apple.product-type.app-extension"; 340 | }; 341 | 8A73D8C725CAE974008DDEA3 /* SwiftPlantUMLApp */ = { 342 | isa = PBXNativeTarget; 343 | buildConfigurationList = 8A73D8D825CAE978008DDEA3 /* Build configuration list for PBXNativeTarget "SwiftPlantUMLApp" */; 344 | buildPhases = ( 345 | 8A73D8C425CAE974008DDEA3 /* Sources */, 346 | 8A73D8C525CAE974008DDEA3 /* Frameworks */, 347 | 8A73D8C625CAE974008DDEA3 /* Resources */, 348 | 8A73D8F325CAE9AA008DDEA3 /* Embed Foundation Extensions */, 349 | 8A73D90925CAE9DD008DDEA3 /* Embed XPC Services */, 350 | ); 351 | buildRules = ( 352 | ); 353 | dependencies = ( 354 | 8A73D8EE25CAE9AA008DDEA3 /* PBXTargetDependency */, 355 | 8A73D90425CAE9DD008DDEA3 /* PBXTargetDependency */, 356 | 192CDFDA2971F5F400CF914F /* PBXTargetDependency */, 357 | ); 358 | name = SwiftPlantUMLApp; 359 | packageProductDependencies = ( 360 | 1919C9C7296B48EA00804361 /* SwiftPlantUMLFramework */, 361 | ); 362 | productName = SwiftPlantUMLApp; 363 | productReference = 8A73D8C825CAE974008DDEA3 /* SwiftPlantUMLApp.app */; 364 | productType = "com.apple.product-type.application"; 365 | }; 366 | 8A73D8DF25CAE9AA008DDEA3 /* SourceEditorExtension */ = { 367 | isa = PBXNativeTarget; 368 | buildConfigurationList = 8A73D8F025CAE9AA008DDEA3 /* Build configuration list for PBXNativeTarget "SourceEditorExtension" */; 369 | buildPhases = ( 370 | 8A73D8DC25CAE9AA008DDEA3 /* Sources */, 371 | 8A73D8DD25CAE9AA008DDEA3 /* Frameworks */, 372 | 8A73D8DE25CAE9AA008DDEA3 /* Resources */, 373 | 8A9E73CC25CAEE2B00327AD1 /* Embed Frameworks */, 374 | 8A73D92725CAEB3B008DDEA3 /* CopyFiles */, 375 | ); 376 | buildRules = ( 377 | ); 378 | dependencies = ( 379 | 8A73D92625CAEB2B008DDEA3 /* PBXTargetDependency */, 380 | ); 381 | name = SourceEditorExtension; 382 | packageProductDependencies = ( 383 | ); 384 | productName = SourceEditorExtension; 385 | productReference = 8A73D8E025CAE9AA008DDEA3 /* SourceEditorExtension.appex */; 386 | productType = "com.apple.product-type.xcode-extension"; 387 | }; 388 | 8A73D8F925CAE9DD008DDEA3 /* XPCService */ = { 389 | isa = PBXNativeTarget; 390 | buildConfigurationList = 8A73D90625CAE9DD008DDEA3 /* Build configuration list for PBXNativeTarget "XPCService" */; 391 | buildPhases = ( 392 | 8A73D8F625CAE9DD008DDEA3 /* Sources */, 393 | 8A73D8F725CAE9DD008DDEA3 /* Frameworks */, 394 | 8A73D8F825CAE9DD008DDEA3 /* Resources */, 395 | ); 396 | buildRules = ( 397 | ); 398 | dependencies = ( 399 | ); 400 | name = XPCService; 401 | packageProductDependencies = ( 402 | 1919C9C9296B48FC00804361 /* SwiftPlantUMLFramework */, 403 | ); 404 | productName = XPCService; 405 | productReference = 8A73D8FA25CAE9DD008DDEA3 /* XPCService.xpc */; 406 | productType = "com.apple.product-type.xpc-service"; 407 | }; 408 | /* End PBXNativeTarget section */ 409 | 410 | /* Begin PBXProject section */ 411 | 8A73D8C025CAE974008DDEA3 /* Project object */ = { 412 | isa = PBXProject; 413 | attributes = { 414 | BuildIndependentTargetsInParallel = YES; 415 | LastSwiftUpdateCheck = 1420; 416 | LastUpgradeCheck = 1500; 417 | TargetAttributes = { 418 | 192CDFCD2971F5F400CF914F = { 419 | CreatedOnToolsVersion = 14.2; 420 | }; 421 | 8A73D8C725CAE974008DDEA3 = { 422 | CreatedOnToolsVersion = 12.4; 423 | }; 424 | 8A73D8DF25CAE9AA008DDEA3 = { 425 | CreatedOnToolsVersion = 12.4; 426 | }; 427 | 8A73D8F925CAE9DD008DDEA3 = { 428 | CreatedOnToolsVersion = 12.4; 429 | LastSwiftMigration = 1240; 430 | }; 431 | }; 432 | }; 433 | buildConfigurationList = 8A73D8C325CAE974008DDEA3 /* Build configuration list for PBXProject "SwiftPlantUMLApp" */; 434 | compatibilityVersion = "Xcode 9.3"; 435 | developmentRegion = en; 436 | hasScannedForEncodings = 0; 437 | knownRegions = ( 438 | en, 439 | Base, 440 | ); 441 | mainGroup = 8A73D8BF25CAE974008DDEA3; 442 | packageReferences = ( 443 | 1919C9C6296B48EA00804361 /* XCRemoteSwiftPackageReference "SwiftPlantUML" */, 444 | ); 445 | productRefGroup = 8A73D8C925CAE974008DDEA3 /* Products */; 446 | projectDirPath = ""; 447 | projectRoot = ""; 448 | targets = ( 449 | 8A73D8C725CAE974008DDEA3 /* SwiftPlantUMLApp */, 450 | 8A73D8DF25CAE9AA008DDEA3 /* SourceEditorExtension */, 451 | 192CDFCD2971F5F400CF914F /* ActionExtension */, 452 | 8A73D8F925CAE9DD008DDEA3 /* XPCService */, 453 | ); 454 | }; 455 | /* End PBXProject section */ 456 | 457 | /* Begin PBXResourcesBuildPhase section */ 458 | 192CDFCC2971F5F400CF914F /* Resources */ = { 459 | isa = PBXResourcesBuildPhase; 460 | buildActionMask = 2147483647; 461 | files = ( 462 | 192CDFD22971F5F400CF914F /* Media.xcassets in Resources */, 463 | ); 464 | runOnlyForDeploymentPostprocessing = 0; 465 | }; 466 | 8A73D8C625CAE974008DDEA3 /* Resources */ = { 467 | isa = PBXResourcesBuildPhase; 468 | buildActionMask = 2147483647; 469 | files = ( 470 | 8A3191792619124B00540446 /* Main.storyboard in Resources */, 471 | 8A73D8D325CAE978008DDEA3 /* Preview Assets.xcassets in Resources */, 472 | 8A73D8D025CAE978008DDEA3 /* Assets.xcassets in Resources */, 473 | ); 474 | runOnlyForDeploymentPostprocessing = 0; 475 | }; 476 | 8A73D8DE25CAE9AA008DDEA3 /* Resources */ = { 477 | isa = PBXResourcesBuildPhase; 478 | buildActionMask = 2147483647; 479 | files = ( 480 | ); 481 | runOnlyForDeploymentPostprocessing = 0; 482 | }; 483 | 8A73D8F825CAE9DD008DDEA3 /* Resources */ = { 484 | isa = PBXResourcesBuildPhase; 485 | buildActionMask = 2147483647; 486 | files = ( 487 | ); 488 | runOnlyForDeploymentPostprocessing = 0; 489 | }; 490 | /* End PBXResourcesBuildPhase section */ 491 | 492 | /* Begin PBXSourcesBuildPhase section */ 493 | 192CDFCA2971F5F400CF914F /* Sources */ = { 494 | isa = PBXSourcesBuildPhase; 495 | buildActionMask = 2147483647; 496 | files = ( 497 | 192CDFD62971F5F400CF914F /* ActionRequestHandler.swift in Sources */, 498 | 192CDFE52971F6DB00CF914F /* XPCServiceProtocol.swift in Sources */, 499 | ); 500 | runOnlyForDeploymentPostprocessing = 0; 501 | }; 502 | 8A73D8C425CAE974008DDEA3 /* Sources */ = { 503 | isa = PBXSourcesBuildPhase; 504 | buildActionMask = 2147483647; 505 | files = ( 506 | 8A42F198279B6B95003BCDB4 /* SettingsView.swift in Sources */, 507 | 8A319170261911B900540446 /* AppDelegate.swift in Sources */, 508 | 8A73D8CE25CAE974008DDEA3 /* ContentView.swift in Sources */, 509 | 8A3191742619123F00540446 /* ViewController.swift in Sources */, 510 | 8A73D8CC25CAE974008DDEA3 /* SwiftPlantUMLAppApp.swift in Sources */, 511 | 8A9F8E6E273EECF300D29025 /* SettingsModel.swift in Sources */, 512 | 8A1EFEF42735DEC000BD6F69 /* Utils.swift in Sources */, 513 | ); 514 | runOnlyForDeploymentPostprocessing = 0; 515 | }; 516 | 8A73D8DC25CAE9AA008DDEA3 /* Sources */ = { 517 | isa = PBXSourcesBuildPhase; 518 | buildActionMask = 2147483647; 519 | files = ( 520 | 8A30356F279BA55700042D19 /* PreferencesCommand.swift in Sources */, 521 | 8A73D8E825CAE9AA008DDEA3 /* SourceEditorExtension.swift in Sources */, 522 | 8A9E73BF25CAEBAF00327AD1 /* XPCServiceProtocol.swift in Sources */, 523 | 8A73D8EA25CAE9AA008DDEA3 /* GenDiagramInBrowser.swift in Sources */, 524 | ); 525 | runOnlyForDeploymentPostprocessing = 0; 526 | }; 527 | 8A73D8F625CAE9DD008DDEA3 /* Sources */ = { 528 | isa = PBXSourcesBuildPhase; 529 | buildActionMask = 2147483647; 530 | files = ( 531 | 8A73D91925CAEA8F008DDEA3 /* XPCServiceProtocol.swift in Sources */, 532 | 8A9F8E6F273EECF300D29025 /* SettingsModel.swift in Sources */, 533 | 8A73D91E25CAEA9E008DDEA3 /* XPCService.swift in Sources */, 534 | 8A73D91425CAEA78008DDEA3 /* main.swift in Sources */, 535 | 8A9F8E68273ED22700D29025 /* Utils.swift in Sources */, 536 | ); 537 | runOnlyForDeploymentPostprocessing = 0; 538 | }; 539 | /* End PBXSourcesBuildPhase section */ 540 | 541 | /* Begin PBXTargetDependency section */ 542 | 192CDFDA2971F5F400CF914F /* PBXTargetDependency */ = { 543 | isa = PBXTargetDependency; 544 | target = 192CDFCD2971F5F400CF914F /* ActionExtension */; 545 | targetProxy = 192CDFD92971F5F400CF914F /* PBXContainerItemProxy */; 546 | }; 547 | 192CDFE42971F68700CF914F /* PBXTargetDependency */ = { 548 | isa = PBXTargetDependency; 549 | target = 8A73D8F925CAE9DD008DDEA3 /* XPCService */; 550 | targetProxy = 192CDFE32971F68700CF914F /* PBXContainerItemProxy */; 551 | }; 552 | 8A73D8EE25CAE9AA008DDEA3 /* PBXTargetDependency */ = { 553 | isa = PBXTargetDependency; 554 | target = 8A73D8DF25CAE9AA008DDEA3 /* SourceEditorExtension */; 555 | targetProxy = 8A73D8ED25CAE9AA008DDEA3 /* PBXContainerItemProxy */; 556 | }; 557 | 8A73D90425CAE9DD008DDEA3 /* PBXTargetDependency */ = { 558 | isa = PBXTargetDependency; 559 | target = 8A73D8F925CAE9DD008DDEA3 /* XPCService */; 560 | targetProxy = 8A73D90325CAE9DD008DDEA3 /* PBXContainerItemProxy */; 561 | }; 562 | 8A73D92625CAEB2B008DDEA3 /* PBXTargetDependency */ = { 563 | isa = PBXTargetDependency; 564 | target = 8A73D8F925CAE9DD008DDEA3 /* XPCService */; 565 | targetProxy = 8A73D92525CAEB2B008DDEA3 /* PBXContainerItemProxy */; 566 | }; 567 | /* End PBXTargetDependency section */ 568 | 569 | /* Begin PBXVariantGroup section */ 570 | 8A3191772619124B00540446 /* Main.storyboard */ = { 571 | isa = PBXVariantGroup; 572 | children = ( 573 | 8A3191782619124B00540446 /* Base */, 574 | ); 575 | name = Main.storyboard; 576 | sourceTree = ""; 577 | }; 578 | /* End PBXVariantGroup section */ 579 | 580 | /* Begin XCBuildConfiguration section */ 581 | 192CDFDC2971F5F400CF914F /* Debug */ = { 582 | isa = XCBuildConfiguration; 583 | buildSettings = { 584 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 585 | CODE_SIGN_ENTITLEMENTS = ActionExtension/ActionExtension.entitlements; 586 | CODE_SIGN_IDENTITY = "Apple Development"; 587 | CODE_SIGN_STYLE = Automatic; 588 | COMBINE_HIDPI_IMAGES = YES; 589 | CURRENT_PROJECT_VERSION = 3; 590 | DEAD_CODE_STRIPPING = YES; 591 | DEVELOPMENT_TEAM = 6V66CC3AN6; 592 | ENABLE_HARDENED_RUNTIME = YES; 593 | GENERATE_INFOPLIST_FILE = YES; 594 | INFOPLIST_FILE = ActionExtension/Info.plist; 595 | INFOPLIST_KEY_CFBundleDisplayName = "View Swift Class Diagram"; 596 | INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023-2024 Marco Eidinger. All rights reserved."; 597 | LD_RUNPATH_SEARCH_PATHS = ( 598 | "$(inherited)", 599 | "@executable_path/../Frameworks", 600 | "@executable_path/../../../../Frameworks", 601 | ); 602 | MACOSX_DEPLOYMENT_TARGET = 10.15; 603 | MARKETING_VERSION = 1.6.0; 604 | PRODUCT_BUNDLE_IDENTIFIER = us.eidinger.SwiftPlantUMLActionExtension; 605 | PRODUCT_NAME = "$(TARGET_NAME)"; 606 | SKIP_INSTALL = YES; 607 | SWIFT_EMIT_LOC_STRINGS = YES; 608 | SWIFT_VERSION = 5.0; 609 | }; 610 | name = Debug; 611 | }; 612 | 192CDFDD2971F5F400CF914F /* Release */ = { 613 | isa = XCBuildConfiguration; 614 | buildSettings = { 615 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; 616 | CODE_SIGN_ENTITLEMENTS = ActionExtension/ActionExtension.entitlements; 617 | CODE_SIGN_IDENTITY = "Apple Development"; 618 | CODE_SIGN_STYLE = Automatic; 619 | COMBINE_HIDPI_IMAGES = YES; 620 | CURRENT_PROJECT_VERSION = 3; 621 | DEAD_CODE_STRIPPING = YES; 622 | DEVELOPMENT_TEAM = 6V66CC3AN6; 623 | ENABLE_HARDENED_RUNTIME = YES; 624 | GENERATE_INFOPLIST_FILE = YES; 625 | INFOPLIST_FILE = ActionExtension/Info.plist; 626 | INFOPLIST_KEY_CFBundleDisplayName = "View Swift Class Diagram"; 627 | INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023-2024 Marco Eidinger. All rights reserved."; 628 | LD_RUNPATH_SEARCH_PATHS = ( 629 | "$(inherited)", 630 | "@executable_path/../Frameworks", 631 | "@executable_path/../../../../Frameworks", 632 | ); 633 | MACOSX_DEPLOYMENT_TARGET = 10.15; 634 | MARKETING_VERSION = 1.6.0; 635 | PRODUCT_BUNDLE_IDENTIFIER = us.eidinger.SwiftPlantUMLActionExtension; 636 | PRODUCT_NAME = "$(TARGET_NAME)"; 637 | SKIP_INSTALL = YES; 638 | SWIFT_EMIT_LOC_STRINGS = YES; 639 | SWIFT_VERSION = 5.0; 640 | }; 641 | name = Release; 642 | }; 643 | 8A73D8D625CAE978008DDEA3 /* Debug */ = { 644 | isa = XCBuildConfiguration; 645 | buildSettings = { 646 | ALWAYS_SEARCH_USER_PATHS = NO; 647 | CLANG_ANALYZER_NONNULL = YES; 648 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 649 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 650 | CLANG_CXX_LIBRARY = "libc++"; 651 | CLANG_ENABLE_MODULES = YES; 652 | CLANG_ENABLE_OBJC_ARC = YES; 653 | CLANG_ENABLE_OBJC_WEAK = YES; 654 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 655 | CLANG_WARN_BOOL_CONVERSION = YES; 656 | CLANG_WARN_COMMA = YES; 657 | CLANG_WARN_CONSTANT_CONVERSION = YES; 658 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 659 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 660 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 661 | CLANG_WARN_EMPTY_BODY = YES; 662 | CLANG_WARN_ENUM_CONVERSION = YES; 663 | CLANG_WARN_INFINITE_RECURSION = YES; 664 | CLANG_WARN_INT_CONVERSION = YES; 665 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 666 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 667 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 668 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 669 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 670 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 671 | CLANG_WARN_STRICT_PROTOTYPES = YES; 672 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 673 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 674 | CLANG_WARN_UNREACHABLE_CODE = YES; 675 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 676 | COPY_PHASE_STRIP = NO; 677 | DEAD_CODE_STRIPPING = YES; 678 | DEBUG_INFORMATION_FORMAT = dwarf; 679 | ENABLE_STRICT_OBJC_MSGSEND = YES; 680 | ENABLE_TESTABILITY = YES; 681 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 682 | GCC_C_LANGUAGE_STANDARD = gnu11; 683 | GCC_DYNAMIC_NO_PIC = NO; 684 | GCC_NO_COMMON_BLOCKS = YES; 685 | GCC_OPTIMIZATION_LEVEL = 0; 686 | GCC_PREPROCESSOR_DEFINITIONS = ( 687 | "DEBUG=1", 688 | "$(inherited)", 689 | ); 690 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 691 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 692 | GCC_WARN_UNDECLARED_SELECTOR = YES; 693 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 694 | GCC_WARN_UNUSED_FUNCTION = YES; 695 | GCC_WARN_UNUSED_VARIABLE = YES; 696 | MACOSX_DEPLOYMENT_TARGET = 10.15; 697 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 698 | MTL_FAST_MATH = YES; 699 | ONLY_ACTIVE_ARCH = YES; 700 | SDKROOT = macosx; 701 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 702 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 703 | }; 704 | name = Debug; 705 | }; 706 | 8A73D8D725CAE978008DDEA3 /* Release */ = { 707 | isa = XCBuildConfiguration; 708 | buildSettings = { 709 | ALWAYS_SEARCH_USER_PATHS = NO; 710 | CLANG_ANALYZER_NONNULL = YES; 711 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 712 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 713 | CLANG_CXX_LIBRARY = "libc++"; 714 | CLANG_ENABLE_MODULES = YES; 715 | CLANG_ENABLE_OBJC_ARC = YES; 716 | CLANG_ENABLE_OBJC_WEAK = YES; 717 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 718 | CLANG_WARN_BOOL_CONVERSION = YES; 719 | CLANG_WARN_COMMA = YES; 720 | CLANG_WARN_CONSTANT_CONVERSION = YES; 721 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 722 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 723 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 724 | CLANG_WARN_EMPTY_BODY = YES; 725 | CLANG_WARN_ENUM_CONVERSION = YES; 726 | CLANG_WARN_INFINITE_RECURSION = YES; 727 | CLANG_WARN_INT_CONVERSION = YES; 728 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 729 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 730 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 731 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 732 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 733 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 734 | CLANG_WARN_STRICT_PROTOTYPES = YES; 735 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 736 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 737 | CLANG_WARN_UNREACHABLE_CODE = YES; 738 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 739 | COPY_PHASE_STRIP = NO; 740 | DEAD_CODE_STRIPPING = YES; 741 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 742 | ENABLE_NS_ASSERTIONS = NO; 743 | ENABLE_STRICT_OBJC_MSGSEND = YES; 744 | ENABLE_USER_SCRIPT_SANDBOXING = YES; 745 | GCC_C_LANGUAGE_STANDARD = gnu11; 746 | GCC_NO_COMMON_BLOCKS = YES; 747 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 748 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 749 | GCC_WARN_UNDECLARED_SELECTOR = YES; 750 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 751 | GCC_WARN_UNUSED_FUNCTION = YES; 752 | GCC_WARN_UNUSED_VARIABLE = YES; 753 | MACOSX_DEPLOYMENT_TARGET = 10.15; 754 | MTL_ENABLE_DEBUG_INFO = NO; 755 | MTL_FAST_MATH = YES; 756 | SDKROOT = macosx; 757 | SWIFT_COMPILATION_MODE = wholemodule; 758 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 759 | }; 760 | name = Release; 761 | }; 762 | 8A73D8D925CAE978008DDEA3 /* Debug */ = { 763 | isa = XCBuildConfiguration; 764 | buildSettings = { 765 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 766 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 767 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 768 | CODE_SIGN_ENTITLEMENTS = SwiftPlantUMLApp/SwiftPlantUMLApp.entitlements; 769 | CODE_SIGN_IDENTITY = "Apple Development"; 770 | CODE_SIGN_STYLE = Automatic; 771 | COMBINE_HIDPI_IMAGES = YES; 772 | CURRENT_PROJECT_VERSION = 3; 773 | DEAD_CODE_STRIPPING = YES; 774 | DEVELOPMENT_ASSET_PATHS = "\"SwiftPlantUMLApp/Preview Content\""; 775 | DEVELOPMENT_TEAM = 6V66CC3AN6; 776 | ENABLE_HARDENED_RUNTIME = YES; 777 | ENABLE_PREVIEWS = YES; 778 | INFOPLIST_FILE = SwiftPlantUMLApp/Info.plist; 779 | LD_RUNPATH_SEARCH_PATHS = ( 780 | "$(inherited)", 781 | "@executable_path/../Frameworks", 782 | ); 783 | MACOSX_DEPLOYMENT_TARGET = 10.15; 784 | MARKETING_VERSION = 1.6.0; 785 | PRODUCT_BUNDLE_IDENTIFIER = us.eidinger.SwiftPlantUML; 786 | PRODUCT_NAME = "$(TARGET_NAME)"; 787 | PROVISIONING_PROFILE_SPECIFIER = ""; 788 | SWIFT_VERSION = 5.0; 789 | }; 790 | name = Debug; 791 | }; 792 | 8A73D8DA25CAE978008DDEA3 /* Release */ = { 793 | isa = XCBuildConfiguration; 794 | buildSettings = { 795 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 796 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 797 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 798 | CODE_SIGN_ENTITLEMENTS = SwiftPlantUMLApp/SwiftPlantUMLApp.entitlements; 799 | CODE_SIGN_IDENTITY = "Apple Development"; 800 | CODE_SIGN_STYLE = Automatic; 801 | COMBINE_HIDPI_IMAGES = YES; 802 | CURRENT_PROJECT_VERSION = 3; 803 | DEAD_CODE_STRIPPING = YES; 804 | DEVELOPMENT_ASSET_PATHS = "\"SwiftPlantUMLApp/Preview Content\""; 805 | DEVELOPMENT_TEAM = 6V66CC3AN6; 806 | ENABLE_HARDENED_RUNTIME = YES; 807 | ENABLE_PREVIEWS = YES; 808 | INFOPLIST_FILE = SwiftPlantUMLApp/Info.plist; 809 | LD_RUNPATH_SEARCH_PATHS = ( 810 | "$(inherited)", 811 | "@executable_path/../Frameworks", 812 | ); 813 | MACOSX_DEPLOYMENT_TARGET = 10.15; 814 | MARKETING_VERSION = 1.6.0; 815 | PRODUCT_BUNDLE_IDENTIFIER = us.eidinger.SwiftPlantUML; 816 | PRODUCT_NAME = "$(TARGET_NAME)"; 817 | PROVISIONING_PROFILE_SPECIFIER = ""; 818 | SWIFT_VERSION = 5.0; 819 | }; 820 | name = Release; 821 | }; 822 | 8A73D8F125CAE9AA008DDEA3 /* Debug */ = { 823 | isa = XCBuildConfiguration; 824 | buildSettings = { 825 | CODE_SIGN_ENTITLEMENTS = SourceEditorExtension/SourceEditorExtension.entitlements; 826 | CODE_SIGN_IDENTITY = "Apple Development"; 827 | CODE_SIGN_STYLE = Automatic; 828 | COMBINE_HIDPI_IMAGES = YES; 829 | CURRENT_PROJECT_VERSION = 3; 830 | DEAD_CODE_STRIPPING = YES; 831 | DEVELOPMENT_TEAM = 6V66CC3AN6; 832 | ENABLE_HARDENED_RUNTIME = YES; 833 | INFOPLIST_FILE = SourceEditorExtension/Info.plist; 834 | LD_RUNPATH_SEARCH_PATHS = ( 835 | "$(inherited)", 836 | "@executable_path/../Frameworks", 837 | "@executable_path/../../../../Frameworks", 838 | ); 839 | MARKETING_VERSION = 1.6.0; 840 | PRODUCT_BUNDLE_IDENTIFIER = us.eidinger.SwiftPlantUMLSourceEditorExtension; 841 | PRODUCT_NAME = "$(TARGET_NAME)"; 842 | PROVISIONING_PROFILE_SPECIFIER = ""; 843 | SKIP_INSTALL = YES; 844 | SWIFT_VERSION = 5.0; 845 | }; 846 | name = Debug; 847 | }; 848 | 8A73D8F225CAE9AA008DDEA3 /* Release */ = { 849 | isa = XCBuildConfiguration; 850 | buildSettings = { 851 | CODE_SIGN_ENTITLEMENTS = SourceEditorExtension/SourceEditorExtension.entitlements; 852 | CODE_SIGN_IDENTITY = "Apple Development"; 853 | CODE_SIGN_STYLE = Automatic; 854 | COMBINE_HIDPI_IMAGES = YES; 855 | CURRENT_PROJECT_VERSION = 3; 856 | DEAD_CODE_STRIPPING = YES; 857 | DEVELOPMENT_TEAM = 6V66CC3AN6; 858 | ENABLE_HARDENED_RUNTIME = YES; 859 | INFOPLIST_FILE = SourceEditorExtension/Info.plist; 860 | LD_RUNPATH_SEARCH_PATHS = ( 861 | "$(inherited)", 862 | "@executable_path/../Frameworks", 863 | "@executable_path/../../../../Frameworks", 864 | ); 865 | MARKETING_VERSION = 1.6.0; 866 | PRODUCT_BUNDLE_IDENTIFIER = us.eidinger.SwiftPlantUMLSourceEditorExtension; 867 | PRODUCT_NAME = "$(TARGET_NAME)"; 868 | PROVISIONING_PROFILE_SPECIFIER = ""; 869 | SKIP_INSTALL = YES; 870 | SWIFT_VERSION = 5.0; 871 | }; 872 | name = Release; 873 | }; 874 | 8A73D90725CAE9DD008DDEA3 /* Debug */ = { 875 | isa = XCBuildConfiguration; 876 | buildSettings = { 877 | CLANG_ENABLE_MODULES = YES; 878 | CODE_SIGN_ENTITLEMENTS = XPCService/XPCService.entitlements; 879 | CODE_SIGN_IDENTITY = "Apple Development"; 880 | CODE_SIGN_STYLE = Automatic; 881 | COMBINE_HIDPI_IMAGES = YES; 882 | CURRENT_PROJECT_VERSION = 3; 883 | DEAD_CODE_STRIPPING = YES; 884 | DEVELOPMENT_TEAM = 6V66CC3AN6; 885 | ENABLE_HARDENED_RUNTIME = YES; 886 | INFOPLIST_FILE = XPCService/Info.plist; 887 | LD_RUNPATH_SEARCH_PATHS = ( 888 | "$(inherited)", 889 | "@executable_path/../Frameworks", 890 | "@loader_path/../Frameworks", 891 | ); 892 | MARKETING_VERSION = 1.6.0; 893 | PRODUCT_BUNDLE_IDENTIFIER = us.eidinger.SwiftPlantUMLXPCService; 894 | PRODUCT_NAME = "$(TARGET_NAME)"; 895 | PROVISIONING_PROFILE_SPECIFIER = ""; 896 | SKIP_INSTALL = YES; 897 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 898 | SWIFT_VERSION = 5.0; 899 | }; 900 | name = Debug; 901 | }; 902 | 8A73D90825CAE9DD008DDEA3 /* Release */ = { 903 | isa = XCBuildConfiguration; 904 | buildSettings = { 905 | CLANG_ENABLE_MODULES = YES; 906 | CODE_SIGN_ENTITLEMENTS = XPCService/XPCService.entitlements; 907 | CODE_SIGN_IDENTITY = "Apple Development"; 908 | CODE_SIGN_STYLE = Automatic; 909 | COMBINE_HIDPI_IMAGES = YES; 910 | CURRENT_PROJECT_VERSION = 3; 911 | DEAD_CODE_STRIPPING = YES; 912 | DEVELOPMENT_TEAM = 6V66CC3AN6; 913 | ENABLE_HARDENED_RUNTIME = YES; 914 | INFOPLIST_FILE = XPCService/Info.plist; 915 | LD_RUNPATH_SEARCH_PATHS = ( 916 | "$(inherited)", 917 | "@executable_path/../Frameworks", 918 | "@loader_path/../Frameworks", 919 | ); 920 | MARKETING_VERSION = 1.6.0; 921 | PRODUCT_BUNDLE_IDENTIFIER = us.eidinger.SwiftPlantUMLXPCService; 922 | PRODUCT_NAME = "$(TARGET_NAME)"; 923 | PROVISIONING_PROFILE_SPECIFIER = ""; 924 | SKIP_INSTALL = YES; 925 | SWIFT_VERSION = 5.0; 926 | }; 927 | name = Release; 928 | }; 929 | /* End XCBuildConfiguration section */ 930 | 931 | /* Begin XCConfigurationList section */ 932 | 192CDFDE2971F5F400CF914F /* Build configuration list for PBXNativeTarget "ActionExtension" */ = { 933 | isa = XCConfigurationList; 934 | buildConfigurations = ( 935 | 192CDFDC2971F5F400CF914F /* Debug */, 936 | 192CDFDD2971F5F400CF914F /* Release */, 937 | ); 938 | defaultConfigurationIsVisible = 0; 939 | defaultConfigurationName = Release; 940 | }; 941 | 8A73D8C325CAE974008DDEA3 /* Build configuration list for PBXProject "SwiftPlantUMLApp" */ = { 942 | isa = XCConfigurationList; 943 | buildConfigurations = ( 944 | 8A73D8D625CAE978008DDEA3 /* Debug */, 945 | 8A73D8D725CAE978008DDEA3 /* Release */, 946 | ); 947 | defaultConfigurationIsVisible = 0; 948 | defaultConfigurationName = Release; 949 | }; 950 | 8A73D8D825CAE978008DDEA3 /* Build configuration list for PBXNativeTarget "SwiftPlantUMLApp" */ = { 951 | isa = XCConfigurationList; 952 | buildConfigurations = ( 953 | 8A73D8D925CAE978008DDEA3 /* Debug */, 954 | 8A73D8DA25CAE978008DDEA3 /* Release */, 955 | ); 956 | defaultConfigurationIsVisible = 0; 957 | defaultConfigurationName = Release; 958 | }; 959 | 8A73D8F025CAE9AA008DDEA3 /* Build configuration list for PBXNativeTarget "SourceEditorExtension" */ = { 960 | isa = XCConfigurationList; 961 | buildConfigurations = ( 962 | 8A73D8F125CAE9AA008DDEA3 /* Debug */, 963 | 8A73D8F225CAE9AA008DDEA3 /* Release */, 964 | ); 965 | defaultConfigurationIsVisible = 0; 966 | defaultConfigurationName = Release; 967 | }; 968 | 8A73D90625CAE9DD008DDEA3 /* Build configuration list for PBXNativeTarget "XPCService" */ = { 969 | isa = XCConfigurationList; 970 | buildConfigurations = ( 971 | 8A73D90725CAE9DD008DDEA3 /* Debug */, 972 | 8A73D90825CAE9DD008DDEA3 /* Release */, 973 | ); 974 | defaultConfigurationIsVisible = 0; 975 | defaultConfigurationName = Release; 976 | }; 977 | /* End XCConfigurationList section */ 978 | 979 | /* Begin XCRemoteSwiftPackageReference section */ 980 | 1919C9C6296B48EA00804361 /* XCRemoteSwiftPackageReference "SwiftPlantUML" */ = { 981 | isa = XCRemoteSwiftPackageReference; 982 | repositoryURL = "https://github.com/MarcoEidinger/SwiftPlantUML.git"; 983 | requirement = { 984 | kind = upToNextMinorVersion; 985 | minimumVersion = 0.8.0; 986 | }; 987 | }; 988 | /* End XCRemoteSwiftPackageReference section */ 989 | 990 | /* Begin XCSwiftPackageProductDependency section */ 991 | 1919C9C7296B48EA00804361 /* SwiftPlantUMLFramework */ = { 992 | isa = XCSwiftPackageProductDependency; 993 | package = 1919C9C6296B48EA00804361 /* XCRemoteSwiftPackageReference "SwiftPlantUML" */; 994 | productName = SwiftPlantUMLFramework; 995 | }; 996 | 1919C9C9296B48FC00804361 /* SwiftPlantUMLFramework */ = { 997 | isa = XCSwiftPackageProductDependency; 998 | package = 1919C9C6296B48EA00804361 /* XCRemoteSwiftPackageReference "SwiftPlantUML" */; 999 | productName = SwiftPlantUMLFramework; 1000 | }; 1001 | 19E9029F29737244002212BA /* SwiftPlantUMLFramework */ = { 1002 | isa = XCSwiftPackageProductDependency; 1003 | package = 1919C9C6296B48EA00804361 /* XCRemoteSwiftPackageReference "SwiftPlantUML" */; 1004 | productName = SwiftPlantUMLFramework; 1005 | }; 1006 | /* End XCSwiftPackageProductDependency section */ 1007 | }; 1008 | rootObject = 8A73D8C025CAE974008DDEA3 /* Project object */; 1009 | } 1010 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "pins" : [ 3 | { 4 | "identity" : "sourcekitten", 5 | "kind" : "remoteSourceControl", 6 | "location" : "https://github.com/jpsim/SourceKitten", 7 | "state" : { 8 | "revision" : "558628392eb31d37cb251cfe626c53eafd330df6", 9 | "version" : "0.31.1" 10 | } 11 | }, 12 | { 13 | "identity" : "swift-argument-parser", 14 | "kind" : "remoteSourceControl", 15 | "location" : "https://github.com/apple/swift-argument-parser.git", 16 | "state" : { 17 | "revision" : "d2930e8fcf9c33162b9fcc1d522bc975e2d4179b", 18 | "version" : "1.0.1" 19 | } 20 | }, 21 | { 22 | "identity" : "swiftplantuml", 23 | "kind" : "remoteSourceControl", 24 | "location" : "https://github.com/MarcoEidinger/SwiftPlantUML.git", 25 | "state" : { 26 | "revision" : "e2e93e026b0d1b4bd8947915e06d6ba5051b2da3", 27 | "version" : "0.8.0" 28 | } 29 | }, 30 | { 31 | "identity" : "swiftybeaver", 32 | "kind" : "remoteSourceControl", 33 | "location" : "https://github.com/SwiftyBeaver/SwiftyBeaver.git", 34 | "state" : { 35 | "revision" : "2c039501d6eeb4d4cd4aec4a8d884ad28862e044", 36 | "version" : "1.9.5" 37 | } 38 | }, 39 | { 40 | "identity" : "swxmlhash", 41 | "kind" : "remoteSourceControl", 42 | "location" : "https://github.com/drmohundro/SWXMLHash.git", 43 | "state" : { 44 | "revision" : "a4931e5c3bafbedeb1601d3bb76bbe835c6d475a", 45 | "version" : "5.0.1" 46 | } 47 | }, 48 | { 49 | "identity" : "yams", 50 | "kind" : "remoteSourceControl", 51 | "location" : "https://github.com/jpsim/Yams.git", 52 | "state" : { 53 | "revision" : "9003d51672e516cc59297b7e96bff1dfdedcb4ea", 54 | "version" : "4.0.4" 55 | } 56 | } 57 | ], 58 | "version" : 2 59 | } 60 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp.xcodeproj/xcshareddata/xcschemes/SourceEditorExtension.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 6 | 9 | 10 | 16 | 22 | 23 | 24 | 30 | 36 | 37 | 38 | 39 | 40 | 45 | 46 | 47 | 48 | 58 | 61 | 62 | 63 | 69 | 70 | 71 | 72 | 80 | 82 | 88 | 89 | 90 | 91 | 93 | 94 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp.xcodeproj/xcshareddata/xcschemes/SwiftPlantUMLApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 45 | 51 | 52 | 53 | 54 | 60 | 62 | 68 | 69 | 70 | 71 | 73 | 74 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import SwiftUI 3 | 4 | @main 5 | class AppDelegate: NSObject, NSApplicationDelegate { 6 | func applicationDidFinishLaunching(_: Notification) { 7 | // Insert code here to initialize your application 8 | NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(handleAppleEvent(event:replyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL)) 9 | } 10 | 11 | func application(_: NSApplication, open _: [URL]) { 12 | showPreferences(self) 13 | } 14 | 15 | @objc func handleAppleEvent(event _: NSAppleEventDescriptor, replyEvent _: NSAppleEventDescriptor) { 16 | showPreferences(self) 17 | } 18 | 19 | @IBAction func showPreferences(_ sender: Any) { 20 | let settingsView = NSHostingView(rootView: SettingsView().environmentObject(ContentViewModel())) 21 | settingsView.translatesAutoresizingMaskIntoConstraints = false 22 | 23 | let controller = NSViewController() 24 | controller.view = settingsView 25 | 26 | let window = NSWindow(contentViewController: controller) 27 | window.title = "Preferences" 28 | 29 | NSWindowController(window: window).showWindow(sender) 30 | } 31 | 32 | @IBAction func showTroubleshootingHelp(_: Any) { 33 | NSWorkspace.shared.open(URL(string: "https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension#troubleshooting")!) 34 | } 35 | 36 | @IBAction func showReleaseNotes(_: Any) { 37 | NSWorkspace.shared.open(URL(string: "https://github.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/releases")!) 38 | } 39 | 40 | @IBAction func showCommandLineToolInfo(_: Any) { 41 | NSWorkspace.shared.open(URL(string: "https://github.com/MarcoEidinger/SwiftPlantUML")!) 42 | } 43 | 44 | func applicationWillTerminate(_: Notification) { 45 | // Insert code here to tear down your application 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/29539e2bd6a45f2e399bb2bcfa0c6f5899481895/SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/29539e2bd6a45f2e399bb2bcfa0c6f5899481895/SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/128.png -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/29539e2bd6a45f2e399bb2bcfa0c6f5899481895/SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/16.png -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/29539e2bd6a45f2e399bb2bcfa0c6f5899481895/SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/256.png -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/29539e2bd6a45f2e399bb2bcfa0c6f5899481895/SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/32.png -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/29539e2bd6a45f2e399bb2bcfa0c6f5899481895/SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/512.png -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/29539e2bd6a45f2e399bb2bcfa0c6f5899481895/SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/64.png -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | {"images":[{"size":"128x128","expected-size":"128","filename":"128.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"256x256","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"128x128","expected-size":"256","filename":"256.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"256x256","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"512x512","expected-size":"512","filename":"512.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"16","filename":"16.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"1x"},{"size":"16x16","expected-size":"32","filename":"32.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"32x32","expected-size":"64","filename":"64.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"},{"size":"512x512","expected-size":"1024","filename":"1024.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"mac","scale":"2x"}]} -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/Color.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "1.000", 9 | "green" : "1.000", 10 | "red" : "1.000" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | }, 15 | { 16 | "appearances" : [ 17 | { 18 | "appearance" : "luminosity", 19 | "value" : "dark" 20 | } 21 | ], 22 | "color" : { 23 | "color-space" : "srgb", 24 | "components" : { 25 | "alpha" : "1.000", 26 | "blue" : "1.000", 27 | "green" : "1.000", 28 | "red" : "1.000" 29 | } 30 | }, 31 | "idiom" : "universal" 32 | } 33 | ], 34 | "info" : { 35 | "author" : "xcode", 36 | "version" : 1 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/Logo.imageset/128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/29539e2bd6a45f2e399bb2bcfa0c6f5899481895/SwiftPlantUMLApp/Assets.xcassets/Logo.imageset/128.png -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/Logo.imageset/256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/29539e2bd6a45f2e399bb2bcfa0c6f5899481895/SwiftPlantUMLApp/Assets.xcassets/Logo.imageset/256.png -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/Logo.imageset/64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/29539e2bd6a45f2e399bb2bcfa0c6f5899481895/SwiftPlantUMLApp/Assets.xcassets/Logo.imageset/64.png -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/Logo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "64.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "128.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "256.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Assets.xcassets/appstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcoEidinger/SwiftPlantUML-Xcode-Extension/29539e2bd6a45f2e399bb2bcfa0c6f5899481895/SwiftPlantUMLApp/Assets.xcassets/appstore.png -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/ContentView.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | class ContentViewModel: ObservableObject { 4 | @Published var settings = SettingsModel() 5 | } 6 | 7 | struct ContentView: View { 8 | @EnvironmentObject private var mainState: ContentViewModel 9 | 10 | @State var selectedConfigurationScope: ConfigurationScope = .elements 11 | 12 | enum ConfigurationScope { 13 | case elements 14 | case members 15 | case others 16 | } 17 | 18 | var body: some View { 19 | HStack { 20 | Image("Logo") 21 | HStack { 22 | VStack(alignment: .leading) { 23 | HStack { 24 | Text("Step 1:") 25 | Button("Open System Preferences") { 26 | DispatchQueue.global().async { 27 | let task = Process() 28 | task.launchPath = "/usr/bin/env" 29 | task.arguments = ["open", "-b", "com.apple.systempreferences", "/System/Library/PreferencePanes/Extensions.prefPane"] 30 | task.launch() 31 | task.waitUntilExit() 32 | } 33 | } 34 | }.padding(5) 35 | HStack { 36 | Text("Step 2:") 37 | Text("Enable: Xcode Source Editor -> SwiftPlantUML").bold() 38 | }.padding(5) 39 | HStack { 40 | Text("Step 2:").hidden() 41 | Text("Enable: Finder -> View Swift Class Diagram").bold() 42 | }.padding(5) 43 | HStack { 44 | Text("Step 3:") 45 | Button("Set Preferences") { 46 | let appDelegate = NSApplication.shared.delegate! as! AppDelegate 47 | appDelegate.showPreferences(self) 48 | } 49 | Text("(Optional)").italic() 50 | }.padding(5) 51 | HStack { 52 | Text("Step 4:") 53 | Button("Close App") { 54 | NSApplication.shared.terminate(nil) 55 | } 56 | }.padding(5) 57 | } 58 | .padding() 59 | } 60 | } 61 | } 62 | } 63 | 64 | struct ContentView_Previews: PreviewProvider { 65 | static var previews: some View { 66 | if #available(macOS 11.0, *) { 67 | ForEach(ColorScheme.allCases, id: \.self, content: 68 | ContentView() 69 | .environmentObject(ContentViewModel()) 70 | .preferredColorScheme) 71 | } else { 72 | ContentView().environmentObject(ContentViewModel()) 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | SwiftPlantUML 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | $(MARKETING_VERSION) 19 | CFBundleURLTypes 20 | 21 | 22 | CFBundleTypeRole 23 | Viewer 24 | CFBundleURLIconFile 25 | 26 | CFBundleURLName 27 | us.eidinger.SwiftPlantUML 28 | CFBundleURLSchemes 29 | 30 | swiftplantumlapp 31 | 32 | 33 | 34 | CFBundleVersion 35 | $(CURRENT_PROJECT_VERSION) 36 | LSApplicationCategoryType 37 | public.app-category.developer-tools 38 | LSMinimumSystemVersion 39 | $(MACOSX_DEPLOYMENT_TARGET) 40 | NSHumanReadableCopyright 41 | Copyright © 2021-2024 Marco Eidinger. All rights reserved. 42 | NSMainStoryboardFile 43 | Main 44 | NSPrincipalClass 45 | NSApplication 46 | 47 | 48 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/SettingsView.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftUI 3 | import SwiftPlantUMLFramework 4 | 5 | extension Theme { 6 | public static var chooseable: [String] { 7 | var values: [String] = [] 8 | values.append("") 9 | values.append(contentsOf: Theme.preferred.map { $0.rawValue }) 10 | return values 11 | } 12 | } 13 | 14 | struct SettingsView: View { 15 | @EnvironmentObject private var mainState: ContentViewModel 16 | 17 | @State var selectedConfigurationScope: ConfigurationScope = .elements 18 | 19 | enum ConfigurationScope { 20 | case elements 21 | case members 22 | case others 23 | } 24 | 25 | var body: some View { 26 | VStack(alignment: .leading) { 27 | HStack { 28 | Text("Choose what should be rendered by SwiftPlantUML") 29 | if #available(macOS 11.0, *) { 30 | Button { 31 | mainState.settings.resetDefaults() 32 | } label: { 33 | Image(systemName: "arrow.uturn.backward") 34 | } 35 | } else { 36 | Button("Reset") { 37 | mainState.settings.resetDefaults() 38 | } 39 | } 40 | } 41 | Text("") 42 | Picker("", selection: $selectedConfigurationScope) { 43 | Text("Elements").tag(ConfigurationScope.elements) 44 | Text("Members").tag(ConfigurationScope.members) 45 | Text("Others").tag(ConfigurationScope.others) 46 | } 47 | .pickerStyle(.segmented) 48 | 49 | VStack(alignment: .leading) { 50 | if selectedConfigurationScope == .elements { 51 | VStack { 52 | Text("having access level") 53 | VStack(alignment: .leading) { 54 | Toggle("Open", isOn: $mainState.settings.showElementsWithAccessLevelOpen) 55 | Toggle("Public", isOn: $mainState.settings.showElementsWithAccessLevelPublic) 56 | Toggle("Package", isOn: $mainState.settings.showElementsWithAccessLevelPackage) 57 | Toggle("Internal", isOn: $mainState.settings.showElementsWithAccessLevelPrivate) 58 | Toggle("Private", isOn: $mainState.settings.showElementsWithAccessLevelInternal) 59 | } 60 | } 61 | Toggle("with no members", isOn: $mainState.settings.showEmptyMembers) 62 | } 63 | if selectedConfigurationScope == .members { 64 | VStack(alignment: .leading) { 65 | Text("having access level") 66 | Toggle("Open", isOn: $mainState.settings.showMembersWithAccessLevelOpen) 67 | Toggle("Public", isOn: $mainState.settings.showMembersWithAccessLevelPublic) 68 | Toggle("Package", isOn: $mainState.settings.showMembersWithAccessLevelPackage) 69 | Toggle("Internal", isOn: $mainState.settings.showMembersWithAccessLevelInternal) 70 | Toggle("Private", isOn: $mainState.settings.showMembersWithAccessLevelPrivate) 71 | } 72 | } 73 | if selectedConfigurationScope == .others { 74 | VStack(alignment: .leading) { 75 | HStack { 76 | Spacer(minLength: 19) 77 | Picker("Theme", selection: $mainState.settings.theme) { 78 | ForEach(Theme.chooseable, id: \.self) { 79 | Text($0) 80 | } 81 | } 82 | Spacer(minLength: 150) 83 | } 84 | HStack { 85 | Spacer(minLength: 19) 86 | Picker("Show extensions", selection: $mainState.settings.showExtensionsValue) { 87 | Text(ExtensionVisualization.all.rawValue).tag(ExtensionVisualization.all.rawValue) 88 | Text(ExtensionVisualization.merged.rawValue).tag(ExtensionVisualization.merged.rawValue) 89 | Text(ExtensionVisualization.none.rawValue).tag(ExtensionVisualization.none.rawValue) 90 | } 91 | Spacer(minLength: 150) 92 | } 93 | Toggle("Show generics", isOn: $mainState.settings.showGenerics) 94 | Toggle("Show nested types", isOn: $mainState.settings.showNestedTypes) 95 | } 96 | } 97 | } 98 | .frame(height: 150) 99 | } 100 | .padding() 101 | .frame(width: 400, height: 250) 102 | } 103 | } 104 | 105 | struct SettingsView_Previews: PreviewProvider { 106 | static var previews: some View { 107 | if #available(macOS 11.0, *) { 108 | ForEach(ColorScheme.allCases, id: \.self, content: 109 | SettingsView() 110 | .environmentObject(ContentViewModel()) 111 | .preferredColorScheme) 112 | } else { 113 | SettingsView() 114 | .environmentObject(ContentViewModel()) 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Shared/SettingsModel.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | struct SettingsModel { 4 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.theme.key, defaultValue: "") 5 | var theme: String 6 | 7 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showGenerics.key, defaultValue: true) 8 | var showGenerics: Bool 9 | 10 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showNestedTypes.key, defaultValue: true) 11 | var showNestedTypes: Bool 12 | 13 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showExtensionsValue.key, defaultValue: "all") 14 | var showExtensionsValue: String 15 | 16 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showEmptyMembers.key, defaultValue: true) 17 | var showEmptyMembers: Bool 18 | 19 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showMembersWithAccessLevelOpen.key, defaultValue: true) 20 | var showMembersWithAccessLevelOpen 21 | 22 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showMembersWithAccessLevelPublic.key, defaultValue: true) 23 | var showMembersWithAccessLevelPublic 24 | 25 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showMembersWithAccessLevelPackage.key, defaultValue: true) 26 | var showMembersWithAccessLevelPackage 27 | 28 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showMembersWithAccessLevelInternal.key, defaultValue: true) 29 | var showMembersWithAccessLevelInternal 30 | 31 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showMembersWithAccessLevelPrivate.key, defaultValue: true) 32 | var showMembersWithAccessLevelPrivate: Bool 33 | 34 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showElementsWithAccessLevelOpen.key, defaultValue: true) 35 | var showElementsWithAccessLevelOpen: Bool 36 | 37 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showElementsWithAccessLevelPublic.key, defaultValue: true) 38 | var showElementsWithAccessLevelPublic: Bool 39 | 40 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showElementsWithAccessLevelPackage.key, defaultValue: true) 41 | var showElementsWithAccessLevelPackage: Bool 42 | 43 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showElementsWithAccessLevelInternal.key, defaultValue: true) 44 | var showElementsWithAccessLevelInternal: Bool 45 | 46 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showElementsWithAccessLevelPrivate.key, defaultValue: true) 47 | var showElementsWithAccessLevelPrivate: Bool 48 | 49 | mutating func resetDefaults() { 50 | theme = "" 51 | showGenerics = true 52 | showNestedTypes = true 53 | showExtensionsValue = "all" 54 | showEmptyMembers = true 55 | showMembersWithAccessLevelOpen = true 56 | showMembersWithAccessLevelPublic = true 57 | showMembersWithAccessLevelPackage = true 58 | showMembersWithAccessLevelInternal = true 59 | showMembersWithAccessLevelPrivate = true 60 | showElementsWithAccessLevelOpen = true 61 | showElementsWithAccessLevelPublic = true 62 | showElementsWithAccessLevelPackage = true 63 | showElementsWithAccessLevelInternal = true 64 | showElementsWithAccessLevelPrivate = true 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/Shared/Utils.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public extension Bool { 4 | func toString() -> String { 5 | self == true ? "true" : "false" 6 | } 7 | } 8 | 9 | public extension UserDefaults { 10 | static let swiftplantumlapp = UserDefaults(suiteName: "group.6V66CC3AN6.us.eidinger.SwiftPlantUML")! 11 | 12 | static func printKeyValues(group _: UserDefaults) { 13 | for (key, value) in UserDefaults.swiftplantumlapp.dictionaryRepresentation() { 14 | print("\(key) = \(value) \n") 15 | } 16 | } 17 | } 18 | 19 | @propertyWrapper struct UserDefaultsWrapper { 20 | let key: String 21 | let defaultValue: T 22 | 23 | init(_ key: String, defaultValue: T) { 24 | self.key = key 25 | self.defaultValue = defaultValue 26 | } 27 | 28 | var wrappedValue: T { 29 | get { 30 | UserDefaults.swiftplantumlapp.object(forKey: key) as? T ?? defaultValue 31 | } 32 | set { 33 | UserDefaults.swiftplantumlapp.set(newValue, forKey: key) 34 | } 35 | } 36 | } 37 | 38 | // MARK: Settings 39 | 40 | public enum UserDefaultsKeys { 41 | public enum SettingsKeys: String, CaseIterable { 42 | case theme 43 | case showGenerics 44 | case showNestedTypes 45 | case showExtensionsValue 46 | case showEmptyMembers 47 | case showMembersWithAccessLevelOpen 48 | case showMembersWithAccessLevelPublic 49 | case showMembersWithAccessLevelPackage 50 | case showMembersWithAccessLevelInternal 51 | case showMembersWithAccessLevelPrivate 52 | case showElementsWithAccessLevelOpen 53 | case showElementsWithAccessLevelPublic 54 | case showElementsWithAccessLevelPackage 55 | case showElementsWithAccessLevelInternal 56 | case showElementsWithAccessLevelPrivate 57 | 58 | var key: String { 59 | "us.eidinger.SwiftPlantUML." + rawValue 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/SwiftPlantUMLApp.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.application-groups 8 | 9 | group.$(TeamIdentifierPrefix)us.eidinger.SwiftPlantUML 10 | 11 | com.apple.security.files.user-selected.read-only 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/SwiftPlantUMLAppApp.swift: -------------------------------------------------------------------------------- 1 | import SwiftUI 2 | 3 | // @main 4 | // struct SwiftPlantUMLAppApp: App { 5 | // @StateObject private var mainState = ContentViewModel() 6 | // 7 | // var body: some Scene { 8 | // WindowGroup { 9 | // ContentView() 10 | // .environmentObject(mainState) 11 | // .frame(width: 800, height: 650) 12 | // } 13 | // } 14 | // } 15 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/ThemeView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ThemeView.swift 3 | // SwiftPlantUMLApp 4 | // 5 | // Created by Marco Eidinger on 1/20/23. 6 | // 7 | 8 | import SwiftUI 9 | 10 | struct ThemeView: View { 11 | var body: some View { 12 | Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) 13 | } 14 | } 15 | 16 | struct ThemeView_Previews: PreviewProvider { 17 | static var previews: some View { 18 | ThemeView() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SwiftPlantUMLApp/ViewController.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import SwiftUI 3 | 4 | class ViewController: NSViewController { 5 | override func viewDidLoad() { 6 | super.viewDidLoad() 7 | 8 | let swiftUIView = NSHostingView(rootView: ContentView().environmentObject(ContentViewModel())) 9 | swiftUIView.translatesAutoresizingMaskIntoConstraints = false 10 | 11 | view.addSubview(swiftUIView) 12 | swiftUIView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true 13 | swiftUIView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true 14 | } 15 | 16 | override var representedObject: Any? { 17 | didSet { 18 | // Update the view, if already loaded. 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /XPCService/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | XPCService 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSHumanReadableCopyright 24 | Copyright © 2021-2024 Marco Eidinger. All rights reserved. 25 | XPCService 26 | 27 | ServiceType 28 | Application 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /XPCService/XPCService.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.$(TeamIdentifierPrefix)us.eidinger.SwiftPlantUML 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /XPCService/XPCService.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import SwiftPlantUMLFramework 3 | 4 | @objc class XPCService: NSObject, XPCServiceProtocol { 5 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.theme.key, defaultValue: "") 6 | var theme: String 7 | 8 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showGenerics.key, defaultValue: true) 9 | var showGenerics: Bool 10 | 11 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showNestedTypes.key, defaultValue: true) 12 | var showNestedTypes: Bool 13 | 14 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showExtensionsValue.key, defaultValue: ExtensionVisualization.default.rawValue) 15 | var showExtensionsValue: String 16 | 17 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showEmptyMembers.key, defaultValue: true) 18 | var showEmptyMembers: Bool 19 | 20 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showMembersWithAccessLevelOpen.key, defaultValue: true) 21 | var showMembersWithAccessLevelOpen: Bool 22 | 23 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showMembersWithAccessLevelPublic.key, defaultValue: true) 24 | var showMembersWithAccessLevelPublic: Bool 25 | 26 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showMembersWithAccessLevelPackage.key, defaultValue: true) 27 | var showMembersWithAccessLevelPackage: Bool 28 | 29 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showMembersWithAccessLevelInternal.key, defaultValue: true) 30 | var showMembersWithAccessLevelInternal: Bool 31 | 32 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showMembersWithAccessLevelPrivate.key, defaultValue: true) 33 | var showMembersWithAccessLevelPrivate: Bool 34 | 35 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showElementsWithAccessLevelOpen.key, defaultValue: true) 36 | var showElementsWithAccessLevelOpen: Bool 37 | 38 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showElementsWithAccessLevelPublic.key, defaultValue: true) 39 | var showElementsWithAccessLevelPublic: Bool 40 | 41 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showElementsWithAccessLevelPackage.key, defaultValue: true) 42 | var showElementsWithAccessLevelPackage: Bool 43 | 44 | 45 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showElementsWithAccessLevelInternal.key, defaultValue: true) 46 | var showElementsWithAccessLevelInternal: Bool 47 | 48 | @UserDefaultsWrapper(UserDefaultsKeys.SettingsKeys.showElementsWithAccessLevelPrivate.key, defaultValue: true) 49 | var showElementsWithAccessLevelPrivate: Bool 50 | 51 | var extensionVisualization: ExtensionVisualization { 52 | ExtensionVisualization(rawValue: showExtensionsValue) ?? .all 53 | } 54 | 55 | var showElementsWithAccessLevel: [AccessLevel] { 56 | var showElementsWithAccessLevel: [AccessLevel] = [] 57 | if showElementsWithAccessLevelOpen { 58 | showElementsWithAccessLevel.append(.open) 59 | } 60 | if showElementsWithAccessLevelPublic { 61 | showElementsWithAccessLevel.append(.public) 62 | } 63 | if showElementsWithAccessLevelPackage { 64 | showElementsWithAccessLevel.append(.package) 65 | } 66 | if showElementsWithAccessLevelInternal { 67 | showElementsWithAccessLevel.append(.internal) 68 | } 69 | if showElementsWithAccessLevelPrivate { 70 | showElementsWithAccessLevel.append(.private) 71 | } 72 | return showElementsWithAccessLevel 73 | } 74 | 75 | var showMembersWithAccessLevel: [AccessLevel] { 76 | var showMembersWithAccessLevel: [AccessLevel] = [] 77 | if showMembersWithAccessLevelOpen { 78 | showMembersWithAccessLevel.append(.open) 79 | } 80 | if showMembersWithAccessLevelPublic { 81 | showMembersWithAccessLevel.append(.public) 82 | } 83 | if showMembersWithAccessLevelPackage { 84 | showMembersWithAccessLevel.append(.package) 85 | } 86 | if showMembersWithAccessLevelInternal { 87 | showMembersWithAccessLevel.append(.internal) 88 | } 89 | if showMembersWithAccessLevelPrivate { 90 | showMembersWithAccessLevel.append(.private) 91 | } 92 | return showMembersWithAccessLevel 93 | } 94 | 95 | var hideShowCommands: [String] { 96 | var hideShowCommands = [String]() 97 | if !showEmptyMembers { 98 | hideShowCommands.append("hide empty members") 99 | } 100 | return hideShowCommands 101 | } 102 | 103 | var selectedTheme: Theme? { 104 | var selTheme: Theme? = nil 105 | if !theme.isEmpty { 106 | selTheme = Theme.__directive__(theme) 107 | } 108 | return selTheme 109 | } 110 | 111 | func generateDiagram(from content: String, completionHandler: @escaping (() -> Void)) { 112 | let config = assembleConfig() 113 | ClassDiagramGenerator().generate(from: content, with: config) 114 | completionHandler() 115 | } 116 | 117 | func generateDiagram(for paths: [String], completionHandler: @escaping (() -> Void)) { 118 | let config = assembleConfig() 119 | ClassDiagramGenerator().generate(for: paths, with: config, presentedBy: PlantUMLBrowserPresenter(format: .svg)) 120 | completionHandler() 121 | } 122 | 123 | func assembleConfig() -> Configuration { 124 | let showNestedTypes = showNestedTypes 125 | let extensionVisualization = extensionVisualization 126 | let selectedTheme = selectedTheme 127 | 128 | return Configuration(elements: ElementOptions(havingAccessLevel: showElementsWithAccessLevel, showMembersWithAccessLevel: showMembersWithAccessLevel, showNestedTypes: showNestedTypes, showGenerics: showGenerics, showExtensions: extensionVisualization, showMemberAccessLevelAttribute: true, exclude: nil), hideShowCommands: hideShowCommands, theme: selectedTheme) 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /XPCService/XPCServiceProtocol.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | @objc protocol XPCServiceProtocol { 4 | func generateDiagram(from content: String, completionHandler: @escaping (() -> Void)) 5 | func generateDiagram(for paths: [String], completionHandler: @escaping (() -> Void)) 6 | } 7 | -------------------------------------------------------------------------------- /XPCService/main.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | class ServiceDelegate: NSObject, NSXPCListenerDelegate { 4 | func listener(_: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool { 5 | newConnection.exportedInterface = NSXPCInterface(with: XPCServiceProtocol.self) 6 | let exportedObject = XPCService() 7 | newConnection.exportedObject = exportedObject 8 | newConnection.resume() 9 | return true 10 | } 11 | } 12 | 13 | // Create the listener and resume it: 14 | let delegate = ServiceDelegate() 15 | let listener = NSXPCListener.service() 16 | listener.delegate = delegate 17 | listener.resume() 18 | --------------------------------------------------------------------------------