@mmerterden/multi-agent-pipeline 20.6.0 → 20.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/LICENSE +0 -10
- package/docs/facts.json +1 -1
- package/manifest.json +328 -329
- package/package.json +2 -2
- package/pipeline/multi-agent-refs/features/design-conformance.md +62 -64
- package/pipeline/scripts/_notices.mjs +12 -1
- package/pipeline/scripts/gen-skills-index.mjs +1 -1
- package/pipeline/skills/.skill-manifest.json +106 -106
- package/pipeline/skills/shared/README.md +71 -71
- package/pipeline/skills/shared/external/agent-introspection-debugging/SKILL.md +1 -0
- package/pipeline/skills/shared/external/alarmkit/SKILL.md +373 -381
- package/pipeline/skills/shared/external/alarmkit/evals/evals.json +23 -18
- package/pipeline/skills/shared/external/alarmkit/references/alarmkit-patterns.md +328 -378
- package/pipeline/skills/shared/external/android-architecture/SKILL.md +2 -0
- package/pipeline/skills/shared/external/android-performance/SKILL.md +2 -0
- package/pipeline/skills/shared/external/android-security/SKILL.md +2 -0
- package/pipeline/skills/shared/external/app-clips/SKILL.md +260 -160
- package/pipeline/skills/shared/external/app-clips/evals/evals.json +27 -27
- package/pipeline/skills/shared/external/app-clips/references/data-handoff-notifications-location.md +150 -83
- package/pipeline/skills/shared/external/app-clips/references/routing-and-experiences.md +135 -83
- package/pipeline/skills/shared/external/app-clips/references/size-capabilities-and-promotion.md +143 -85
- package/pipeline/skills/shared/external/app-intents/SKILL.md +302 -304
- package/pipeline/skills/shared/external/app-intents/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-intents/references/appintents-advanced.md +594 -894
- package/pipeline/skills/shared/external/app-store-optimization/SKILL.md +339 -277
- package/pipeline/skills/shared/external/app-store-optimization/evals/evals.json +27 -23
- package/pipeline/skills/shared/external/app-store-optimization/references/keyword-research-methodology.md +105 -122
- package/pipeline/skills/shared/external/app-store-optimization/references/product-page-variants.md +143 -166
- package/pipeline/skills/shared/external/app-store-review/SKILL.md +307 -326
- package/pipeline/skills/shared/external/app-store-review/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/app-store-review/references/privacy-manifest.md +105 -67
- package/pipeline/skills/shared/external/app-store-review/references/review-checklists.md +114 -101
- package/pipeline/skills/shared/external/apple-on-device-ai/SKILL.md +333 -360
- package/pipeline/skills/shared/external/apple-on-device-ai/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-conversion.md +215 -322
- package/pipeline/skills/shared/external/apple-on-device-ai/references/coreml-optimization.md +161 -256
- package/pipeline/skills/shared/external/apple-on-device-ai/references/foundation-models.md +277 -387
- package/pipeline/skills/shared/external/apple-on-device-ai/references/mlx-swift.md +196 -210
- package/pipeline/skills/shared/external/authentication/SKILL.md +265 -381
- package/pipeline/skills/shared/external/authentication/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/authentication/references/keychain-biometric.md +133 -178
- package/pipeline/skills/shared/external/authentication/references/passkeys.md +111 -147
- package/pipeline/skills/shared/external/avkit/SKILL.md +267 -364
- package/pipeline/skills/shared/external/avkit/evals/evals.json +26 -26
- package/pipeline/skills/shared/external/avkit/references/avkit-patterns.md +375 -493
- package/pipeline/skills/shared/external/background-processing/SKILL.md +270 -382
- package/pipeline/skills/shared/external/background-processing/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/background-processing/references/background-task-patterns.md +169 -317
- package/pipeline/skills/shared/external/backlog/BACKLOG.md +1 -1
- package/pipeline/skills/shared/external/backlog/SKILL.md +56 -33
- package/pipeline/skills/shared/external/callkit-voip/SKILL.md +290 -371
- package/pipeline/skills/shared/external/callkit-voip/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/callkit-voip/references/callkit-patterns.md +175 -343
- package/pipeline/skills/shared/external/ci-cd-pipelines/SKILL.md +1 -0
- package/pipeline/skills/shared/external/cloudkit-sync/SKILL.md +292 -381
- package/pipeline/skills/shared/external/cloudkit-sync/evals/evals.json +33 -30
- package/pipeline/skills/shared/external/cloudkit-sync/references/cloudkit-patterns.md +227 -355
- package/pipeline/skills/shared/external/compose-components/SKILL.md +2 -0
- package/pipeline/skills/shared/external/compose-navigation/SKILL.md +3 -2
- package/pipeline/skills/shared/external/compose-testing/SKILL.md +2 -0
- package/pipeline/skills/shared/external/contacts-framework/SKILL.md +197 -346
- package/pipeline/skills/shared/external/contacts-framework/evals/evals.json +19 -21
- package/pipeline/skills/shared/external/contacts-framework/references/contacts-patterns.md +169 -308
- package/pipeline/skills/shared/external/core-bluetooth/SKILL.md +226 -376
- package/pipeline/skills/shared/external/core-bluetooth/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/core-bluetooth/references/ble-patterns.md +257 -337
- package/pipeline/skills/shared/external/core-data/SKILL.md +292 -368
- package/pipeline/skills/shared/external/core-data/evals/evals.json +30 -27
- package/pipeline/skills/shared/external/core-motion/SKILL.md +235 -324
- package/pipeline/skills/shared/external/core-motion/evals/evals.json +31 -27
- package/pipeline/skills/shared/external/core-motion/references/motion-patterns.md +210 -310
- package/pipeline/skills/shared/external/core-nfc/SKILL.md +292 -366
- package/pipeline/skills/shared/external/core-nfc/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/core-nfc/references/nfc-patterns.md +233 -329
- package/pipeline/skills/shared/external/coreml/SKILL.md +323 -367
- package/pipeline/skills/shared/external/coreml/evals/evals.json +24 -21
- package/pipeline/skills/shared/external/coreml/references/coreml-swift-integration.md +562 -565
- package/pipeline/skills/shared/external/council/SKILL.md +1 -0
- package/pipeline/skills/shared/external/cryptokit/SKILL.md +253 -394
- package/pipeline/skills/shared/external/cryptokit/evals/evals.json +20 -18
- package/pipeline/skills/shared/external/cryptokit/references/cryptokit-patterns.md +299 -488
- package/pipeline/skills/shared/external/css-modern/SKILL.md +1 -0
- package/pipeline/skills/shared/external/database-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/debugging-instruments/SKILL.md +270 -323
- package/pipeline/skills/shared/external/debugging-instruments/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/debugging-instruments/references/instruments-guide.md +167 -315
- package/pipeline/skills/shared/external/debugging-instruments/references/lldb-patterns.md +140 -193
- package/pipeline/skills/shared/external/device-integrity/SKILL.md +230 -353
- package/pipeline/skills/shared/external/device-integrity/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/device-integrity/references/device-integrity-patterns.md +159 -197
- package/pipeline/skills/shared/external/energykit/SKILL.md +225 -392
- package/pipeline/skills/shared/external/energykit/evals/evals.json +29 -28
- package/pipeline/skills/shared/external/energykit/references/energykit-patterns.md +174 -470
- package/pipeline/skills/shared/external/eventkit-calendar/SKILL.md +261 -383
- package/pipeline/skills/shared/external/eventkit-calendar/evals/evals.json +25 -22
- package/pipeline/skills/shared/external/eventkit-calendar/references/eventkit-patterns.md +165 -268
- package/pipeline/skills/shared/external/evidence-github/SKILL.md +2 -0
- package/pipeline/skills/shared/external/evidence-registry/SKILL.md +2 -0
- package/pipeline/skills/shared/external/gradle-kotlin-dsl/SKILL.md +2 -0
- package/pipeline/skills/shared/external/healthkit/SKILL.md +252 -303
- package/pipeline/skills/shared/external/healthkit/evals/evals.json +24 -23
- package/pipeline/skills/shared/external/healthkit/references/healthkit-patterns.md +369 -523
- package/pipeline/skills/shared/external/homekit-matter/SKILL.md +233 -348
- package/pipeline/skills/shared/external/homekit-matter/evals/evals.json +27 -22
- package/pipeline/skills/shared/external/homekit-matter/references/matter-commissioning.md +199 -305
- package/pipeline/skills/shared/external/html-semantic/SKILL.md +1 -0
- package/pipeline/skills/shared/external/humanizer/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-accessibility/SKILL.md +368 -340
- package/pipeline/skills/shared/external/ios-accessibility/evals/evals.json +28 -27
- package/pipeline/skills/shared/external/ios-accessibility/references/a11y-patterns.md +314 -260
- package/pipeline/skills/shared/external/ios-accessibility/references/media-accessibility.md +97 -67
- package/pipeline/skills/shared/external/ios-accessibility/references/nutrition-labels.md +165 -101
- package/pipeline/skills/shared/external/ios-coding-standard/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-localization/SKILL.md +258 -371
- package/pipeline/skills/shared/external/ios-localization/evals/evals.json +23 -23
- package/pipeline/skills/shared/external/ios-localization/references/formatstyle-locale.md +283 -491
- package/pipeline/skills/shared/external/ios-localization/references/string-catalogs.md +313 -440
- package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +1 -0
- package/pipeline/skills/shared/external/ios-networking/SKILL.md +265 -341
- package/pipeline/skills/shared/external/ios-networking/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/ios-networking/references/background-websocket.md +425 -652
- package/pipeline/skills/shared/external/ios-networking/references/file-storage-patterns.md +143 -285
- package/pipeline/skills/shared/external/ios-networking/references/lightweight-clients.md +93 -53
- package/pipeline/skills/shared/external/ios-networking/references/network-framework.md +231 -456
- package/pipeline/skills/shared/external/ios-networking/references/urlsession-patterns.md +517 -784
- package/pipeline/skills/shared/external/ios-security/SKILL.md +2 -0
- package/pipeline/skills/shared/external/ios-simulator/SKILL.md +265 -393
- package/pipeline/skills/shared/external/ios-simulator/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/ios-simulator/references/simctl-commands.md +177 -270
- package/pipeline/skills/shared/external/live-activities/SKILL.md +318 -360
- package/pipeline/skills/shared/external/live-activities/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/live-activities/references/activitykit-patterns.md +478 -710
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +91 -283
- package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +119 -151
- package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +60 -90
- package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +119 -156
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +726 -787
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +253 -288
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +243 -304
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +88 -104
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +181 -235
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +198 -263
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +461 -466
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +145 -151
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +123 -141
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +146 -157
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +22 -19
- package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +156 -140
- package/pipeline/skills/shared/external/mapkit-location/SKILL.md +295 -267
- package/pipeline/skills/shared/external/mapkit-location/evals/evals.json +28 -24
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-corelocation-patterns.md +378 -532
- package/pipeline/skills/shared/external/mapkit-location/references/mapkit-patterns.md +397 -499
- package/pipeline/skills/shared/external/metrickit-diagnostics/SKILL.md +165 -348
- package/pipeline/skills/shared/external/metrickit-diagnostics/evals/evals.json +26 -23
- package/pipeline/skills/shared/external/metrickit-diagnostics/references/metrickit-patterns.md +123 -130
- package/pipeline/skills/shared/external/musickit-audio/SKILL.md +189 -315
- package/pipeline/skills/shared/external/musickit-audio/evals/evals.json +22 -21
- package/pipeline/skills/shared/external/musickit-audio/references/musickit-patterns.md +181 -270
- package/pipeline/skills/shared/external/natural-language/SKILL.md +188 -340
- package/pipeline/skills/shared/external/natural-language/evals/evals.json +21 -21
- package/pipeline/skills/shared/external/natural-language/references/translation-patterns.md +171 -225
- package/pipeline/skills/shared/external/nextjs-app-router/SKILL.md +1 -0
- package/pipeline/skills/shared/external/passkit-wallet/SKILL.md +258 -392
- package/pipeline/skills/shared/external/passkit-wallet/evals/evals.json +30 -29
- package/pipeline/skills/shared/external/passkit-wallet/references/wallet-passes.md +164 -231
- package/pipeline/skills/shared/external/pdfkit/SKILL.md +312 -344
- package/pipeline/skills/shared/external/pdfkit/evals/evals.json +19 -19
- package/pipeline/skills/shared/external/pdfkit/references/pdfkit-patterns.md +413 -624
- package/pipeline/skills/shared/external/pencilkit-drawing/SKILL.md +242 -358
- package/pipeline/skills/shared/external/pencilkit-drawing/evals/evals.json +25 -21
- package/pipeline/skills/shared/external/pencilkit-drawing/references/pencilkit-patterns.md +161 -226
- package/pipeline/skills/shared/external/permissionkit/SKILL.md +282 -400
- package/pipeline/skills/shared/external/permissionkit/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/permissionkit/references/permissionkit-patterns.md +237 -350
- package/pipeline/skills/shared/external/photos-camera-media/SKILL.md +276 -325
- package/pipeline/skills/shared/external/photos-camera-media/references/av-playback.md +299 -545
- package/pipeline/skills/shared/external/photos-camera-media/references/camera-capture.md +344 -588
- package/pipeline/skills/shared/external/photos-camera-media/references/image-loading-caching.md +316 -660
- package/pipeline/skills/shared/external/photos-camera-media/references/photokit-patterns.md +270 -416
- package/pipeline/skills/shared/external/play-store-review/SKILL.md +2 -0
- package/pipeline/skills/shared/external/push-notifications/SKILL.md +312 -340
- package/pipeline/skills/shared/external/push-notifications/evals/evals.json +27 -26
- package/pipeline/skills/shared/external/push-notifications/references/notification-patterns.md +328 -485
- package/pipeline/skills/shared/external/push-notifications/references/rich-notifications.md +327 -560
- package/pipeline/skills/shared/external/python-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/react-best-practices/SKILL.md +1 -0
- package/pipeline/skills/shared/external/realitykit-ar/SKILL.md +218 -410
- package/pipeline/skills/shared/external/realitykit-ar/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/realitykit-ar/references/realitykit-patterns.md +221 -348
- package/pipeline/skills/shared/external/rest-api-design/SKILL.md +1 -0
- package/pipeline/skills/shared/external/retrofit-networking/SKILL.md +2 -0
- package/pipeline/skills/shared/external/room-database/SKILL.md +2 -0
- package/pipeline/skills/shared/external/search-first/SKILL.md +1 -0
- package/pipeline/skills/shared/external/shareplay-activities/SKILL.md +222 -393
- package/pipeline/skills/shared/external/shareplay-activities/evals/evals.json +23 -24
- package/pipeline/skills/shared/external/shareplay-activities/references/shareplay-patterns.md +280 -420
- package/pipeline/skills/shared/external/signal-community/SKILL.md +2 -0
- package/pipeline/skills/shared/external/skill-creator/SKILL.md +80 -41
- package/pipeline/skills/shared/external/skill-creator/audit.md +63 -59
- package/pipeline/skills/shared/external/skill-creator/checklist.md +28 -20
- package/pipeline/skills/shared/external/skill-creator/examples.md +40 -40
- package/pipeline/skills/shared/external/skill-creator/label-check.md +48 -36
- package/pipeline/skills/shared/external/skill-creator/scripts/audit-panel.js +91 -100
- package/pipeline/skills/shared/external/skill-creator/template.md +51 -39
- package/pipeline/skills/shared/external/speech-recognition/SKILL.md +217 -421
- package/pipeline/skills/shared/external/speech-recognition/evals/evals.json +23 -26
- package/pipeline/skills/shared/external/speech-recognition/references/speechanalyzer-patterns.md +133 -125
- package/pipeline/skills/shared/external/storekit/SKILL.md +228 -204
- package/pipeline/skills/shared/external/storekit/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/storekit/references/app-review-guidelines.md +98 -109
- package/pipeline/skills/shared/external/storekit/references/core-patterns.md +298 -242
- package/pipeline/skills/shared/external/storekit/references/storekit-advanced.md +356 -649
- package/pipeline/skills/shared/external/swift-api-design-guidelines/SKILL.md +274 -399
- package/pipeline/skills/shared/external/swift-api-design-guidelines/evals/evals.json +22 -24
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/argument-labels-and-parameters.md +107 -108
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/conventions-and-special-rules.md +93 -165
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/naming-and-clarity.md +99 -137
- package/pipeline/skills/shared/external/swift-api-design-guidelines/references/side-effects-and-mutating-pairs.md +77 -120
- package/pipeline/skills/shared/external/swift-architecture/SKILL.md +334 -350
- package/pipeline/skills/shared/external/swift-architecture/evals/evals.json +22 -22
- package/pipeline/skills/shared/external/swift-charts/SKILL.md +208 -394
- package/pipeline/skills/shared/external/swift-charts/evals/evals.json +27 -30
- package/pipeline/skills/shared/external/swift-charts/references/charts-patterns.md +351 -762
- package/pipeline/skills/shared/external/swift-codable/SKILL.md +339 -343
- package/pipeline/skills/shared/external/swift-codable/evals/evals.json +20 -20
- package/pipeline/skills/shared/external/swift-concurrency/SKILL.md +303 -351
- package/pipeline/skills/shared/external/swift-concurrency/evals/evals.json +27 -24
- package/pipeline/skills/shared/external/swift-concurrency/references/approachable-concurrency.md +65 -80
- package/pipeline/skills/shared/external/swift-concurrency/references/async-algorithms.md +48 -84
- package/pipeline/skills/shared/external/swift-concurrency/references/bridging-interop.md +134 -79
- package/pipeline/skills/shared/external/swift-concurrency/references/concurrency-patterns.md +145 -167
- package/pipeline/skills/shared/external/swift-concurrency/references/diagnostics.md +62 -50
- package/pipeline/skills/shared/external/swift-concurrency/references/swiftui-concurrency.md +92 -121
- package/pipeline/skills/shared/external/swift-concurrency/references/synchronization-primitives.md +177 -241
- package/pipeline/skills/shared/external/swift-formatstyle/SKILL.md +258 -234
- package/pipeline/skills/shared/external/swift-language/SKILL.md +342 -382
- package/pipeline/skills/shared/external/swift-language/evals/evals.json +24 -27
- package/pipeline/skills/shared/external/swift-language/references/swift-attributes-interop.md +79 -56
- package/pipeline/skills/shared/external/swift-language/references/swift-patterns-extended.md +297 -340
- package/pipeline/skills/shared/external/swift-security/SKILL.md +180 -161
- package/pipeline/skills/shared/external/swift-security/evals/evals.json +25 -25
- package/pipeline/skills/shared/external/swift-security/references/biometric-authentication.md +314 -469
- package/pipeline/skills/shared/external/swift-security/references/certificate-trust.md +408 -476
- package/pipeline/skills/shared/external/swift-security/references/common-anti-patterns.md +260 -530
- package/pipeline/skills/shared/external/swift-security/references/compliance-owasp-mapping.md +270 -477
- package/pipeline/skills/shared/external/swift-security/references/credential-storage-patterns.md +573 -571
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-public-key.md +370 -441
- package/pipeline/skills/shared/external/swift-security/references/cryptokit-symmetric.md +332 -433
- package/pipeline/skills/shared/external/swift-security/references/keychain-access-control.md +346 -468
- package/pipeline/skills/shared/external/swift-security/references/keychain-fundamentals.md +352 -472
- package/pipeline/skills/shared/external/swift-security/references/keychain-item-classes.md +431 -432
- package/pipeline/skills/shared/external/swift-security/references/keychain-sharing.md +328 -425
- package/pipeline/skills/shared/external/swift-security/references/migration-legacy-stores.md +341 -579
- package/pipeline/skills/shared/external/swift-security/references/secure-enclave.md +396 -457
- package/pipeline/skills/shared/external/swift-security/references/testing-security-code.md +354 -614
- package/pipeline/skills/shared/external/swift-testing/SKILL.md +188 -175
- package/pipeline/skills/shared/external/swift-testing/evals/evals.json +26 -24
- package/pipeline/skills/shared/external/swift-testing/references/testing-advanced.md +80 -84
- package/pipeline/skills/shared/external/swift-testing/references/testing-patterns.md +317 -433
- package/pipeline/skills/shared/external/swiftdata/SKILL.md +392 -256
- package/pipeline/skills/shared/external/swiftdata/evals/evals.json +24 -24
- package/pipeline/skills/shared/external/swiftdata/references/core-data-coexistence.md +206 -402
- package/pipeline/skills/shared/external/swiftdata/references/indexing.md +59 -52
- package/pipeline/skills/shared/external/swiftdata/references/predicate-pitfalls.md +57 -33
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-advanced.md +354 -747
- package/pipeline/skills/shared/external/swiftdata/references/swiftdata-queries.md +300 -508
- package/pipeline/skills/shared/external/swiftlint/SKILL.md +175 -226
- package/pipeline/skills/shared/external/swiftlint/references/adoption-and-configuration.md +141 -208
- package/pipeline/skills/shared/external/swiftlint/references/custom-rules-and-analyze.md +100 -109
- package/pipeline/skills/shared/external/swiftlint/references/plugins-run-scripts-and-integrations.md +159 -179
- package/pipeline/skills/shared/external/swiftlint/references/rule-reference.md +383 -18
- package/pipeline/skills/shared/external/swiftlint/references/rules-suppressions-and-baselines.md +143 -229
- package/pipeline/skills/shared/external/swiftui-animation/SKILL.md +283 -366
- package/pipeline/skills/shared/external/swiftui-animation/references/animation-advanced.md +396 -608
- package/pipeline/skills/shared/external/swiftui-animation/references/core-animation-bridge.md +336 -385
- package/pipeline/skills/shared/external/swiftui-gestures/SKILL.md +239 -349
- package/pipeline/skills/shared/external/swiftui-gestures/references/gesture-patterns.md +228 -310
- package/pipeline/skills/shared/external/swiftui-layout-components/SKILL.md +260 -249
- package/pipeline/skills/shared/external/swiftui-layout-components/references/form.md +92 -74
- package/pipeline/skills/shared/external/swiftui-layout-components/references/grids.md +112 -177
- package/pipeline/skills/shared/external/swiftui-layout-components/references/list.md +61 -64
- package/pipeline/skills/shared/external/swiftui-layout-components/references/scrollview.md +94 -134
- package/pipeline/skills/shared/external/swiftui-liquid-glass/SKILL.md +193 -225
- package/pipeline/skills/shared/external/swiftui-liquid-glass/references/liquid-glass.md +173 -327
- package/pipeline/skills/shared/external/swiftui-navigation/SKILL.md +193 -168
- package/pipeline/skills/shared/external/swiftui-navigation/references/deeplinks.md +127 -150
- package/pipeline/skills/shared/external/swiftui-navigation/references/navigationstack.md +132 -133
- package/pipeline/skills/shared/external/swiftui-navigation/references/sheets.md +152 -117
- package/pipeline/skills/shared/external/swiftui-navigation/references/tabview.md +106 -140
- package/pipeline/skills/shared/external/swiftui-patterns/SKILL.md +316 -252
- package/pipeline/skills/shared/external/swiftui-patterns/references/architecture-patterns.md +341 -332
- package/pipeline/skills/shared/external/swiftui-patterns/references/deprecated-migration.md +547 -854
- package/pipeline/skills/shared/external/swiftui-patterns/references/design-polish.md +485 -537
- package/pipeline/skills/shared/external/swiftui-patterns/references/platform-and-sharing.md +417 -499
- package/pipeline/skills/shared/external/swiftui-performance/SKILL.md +213 -376
- package/pipeline/skills/shared/external/swiftui-performance/references/demystify-swiftui-performance-wwdc23.md +86 -175
- package/pipeline/skills/shared/external/swiftui-performance/references/optimizing-swiftui-performance-instruments.md +89 -195
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-hangs-in-your-app.md +95 -182
- package/pipeline/skills/shared/external/swiftui-performance/references/understanding-improving-swiftui-performance.md +71 -149
- package/pipeline/skills/shared/external/swiftui-performance/references/wwdc-session-sources.md +21 -27
- package/pipeline/skills/shared/external/swiftui-uikit-interop/SKILL.md +303 -295
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/hosting-migration.md +204 -387
- package/pipeline/skills/shared/external/swiftui-uikit-interop/references/representable-recipes.md +469 -683
- package/pipeline/skills/shared/external/swiftui-webkit/SKILL.md +140 -186
- package/pipeline/skills/shared/external/swiftui-webkit/references/loading-and-observation.md +75 -86
- package/pipeline/skills/shared/external/swiftui-webkit/references/local-content-and-custom-schemes.md +63 -60
- package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md +69 -137
- package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md +95 -67
- package/pipeline/skills/shared/external/tailwind-css/SKILL.md +1 -0
- package/pipeline/skills/shared/external/testing-backend/SKILL.md +1 -0
- package/pipeline/skills/shared/external/tipkit/SKILL.md +220 -335
- package/pipeline/skills/shared/external/tipkit/references/tipkit-patterns.md +356 -494
- package/pipeline/skills/shared/external/typescript-patterns/SKILL.md +1 -0
- package/pipeline/skills/shared/external/vision-framework/SKILL.md +260 -375
- package/pipeline/skills/shared/external/vision-framework/references/vision-requests.md +393 -515
- package/pipeline/skills/shared/external/vision-framework/references/visionkit-scanner.md +363 -539
- package/pipeline/skills/shared/external/vue-composition/SKILL.md +1 -0
- package/pipeline/skills/shared/external/weatherkit/SKILL.md +152 -310
- package/pipeline/skills/shared/external/weatherkit/references/weatherkit-patterns.md +288 -407
- package/pipeline/skills/shared/external/web-accessibility/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-performance/SKILL.md +1 -0
- package/pipeline/skills/shared/external/web-testing/SKILL.md +1 -0
- package/pipeline/skills/shared/external/widgetkit/SKILL.md +216 -288
- package/pipeline/skills/shared/external/widgetkit/references/widgetkit-advanced.md +414 -719
- package/pipeline/skills/shared/external/NOTICE-swift-ios-skills.md +0 -39
|
@@ -1,95 +1,98 @@
|
|
|
1
|
-
# Local
|
|
1
|
+
# Local content and custom URL schemes
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
- When to use custom schemes
|
|
5
|
-
- Registering a scheme handler
|
|
6
|
-
- Returning responses and data
|
|
7
|
-
- Loading bundled content
|
|
8
|
-
- Cancellation behavior
|
|
3
|
+
Part of the `swiftui-webkit` skill ([../SKILL.md](../SKILL.md)).
|
|
9
4
|
|
|
10
|
-
##
|
|
5
|
+
## Where a custom scheme fits
|
|
11
6
|
|
|
12
|
-
|
|
7
|
+
Good candidates:
|
|
13
8
|
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
- app-owned rich content assembled on device
|
|
9
|
+
- HTML, CSS and JavaScript shipped inside the app bundle
|
|
10
|
+
- documentation that must work offline
|
|
11
|
+
- rich content the app assembles on the device
|
|
18
12
|
|
|
19
|
-
|
|
13
|
+
Ordinary pages that live on a server are not candidates; load those over
|
|
14
|
+
HTTPS.
|
|
20
15
|
|
|
21
|
-
## Registering
|
|
16
|
+
## Registering the handler
|
|
17
|
+
|
|
18
|
+
Put the registration in one main-actor factory so every screen gets the same
|
|
19
|
+
setup.
|
|
22
20
|
|
|
23
21
|
```swift
|
|
24
|
-
import Foundation
|
|
25
22
|
import WebKit
|
|
26
23
|
|
|
27
24
|
@MainActor
|
|
28
|
-
func
|
|
29
|
-
var
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
func makeManualPage() -> WebPage {
|
|
26
|
+
var setup = WebPage.Configuration()
|
|
27
|
+
if let scheme = URLScheme("manual") {
|
|
28
|
+
setup.urlSchemeHandlers[scheme] = ManualFiles()
|
|
29
|
+
}
|
|
30
|
+
return WebPage(configuration: setup)
|
|
32
31
|
}
|
|
33
32
|
```
|
|
34
33
|
|
|
35
|
-
|
|
34
|
+
Schemes WebKit already owns cannot be taken over: registering
|
|
35
|
+
`URLScheme("https")` has no effect. Pick a name that is really yours.
|
|
36
36
|
|
|
37
|
-
##
|
|
37
|
+
## Producing the response
|
|
38
38
|
|
|
39
|
-
A handler
|
|
39
|
+
A handler implements `reply(for:)` and returns an async sequence of
|
|
40
|
+
`URLSchemeTaskResult` values. Send a `.response(_:)` first, then one or more
|
|
41
|
+
`.data(_:)` chunks; for multi-part content the two can alternate.
|
|
40
42
|
|
|
41
43
|
```swift
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
import Foundation
|
|
45
|
+
import WebKit
|
|
46
|
+
|
|
47
|
+
struct ManualFiles: URLSchemeHandler {
|
|
48
|
+
func reply(for request: URLRequest) -> AsyncThrowingStream<URLSchemeTaskResult, any Error> {
|
|
49
|
+
AsyncThrowingStream { continuation in
|
|
50
|
+
guard let address = request.url,
|
|
51
|
+
let chapter = address.host(),
|
|
52
|
+
let file = Bundle.main.url(forResource: chapter,
|
|
53
|
+
withExtension: "html",
|
|
54
|
+
subdirectory: "Manual"),
|
|
55
|
+
let body = try? Data(contentsOf: file) else {
|
|
56
|
+
continuation.finish(throwing: URLError(.fileDoesNotExist))
|
|
51
57
|
return
|
|
52
58
|
}
|
|
53
59
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
)
|
|
62
|
-
continuation.yield(.response(response))
|
|
63
|
-
continuation.yield(.data(data))
|
|
64
|
-
continuation.finish()
|
|
65
|
-
} catch {
|
|
66
|
-
continuation.finish()
|
|
67
|
-
}
|
|
60
|
+
let head = URLResponse(url: address,
|
|
61
|
+
mimeType: "text/html",
|
|
62
|
+
expectedContentLength: body.count,
|
|
63
|
+
textEncodingName: "utf-8")
|
|
64
|
+
continuation.yield(.response(head))
|
|
65
|
+
continuation.yield(.data(body))
|
|
66
|
+
continuation.finish()
|
|
68
67
|
}
|
|
69
68
|
}
|
|
70
69
|
}
|
|
71
70
|
```
|
|
72
71
|
|
|
73
|
-
Keep
|
|
72
|
+
Keep `mimeType` and `textEncodingName` truthful: a stylesheet served as
|
|
73
|
+
`text/html` or UTF-16 labelled as UTF-8 renders wrongly. The protocol
|
|
74
|
+
requires a sequence whose failure type is `any Error`, so a throwing stream
|
|
75
|
+
is the natural choice and lets a missing file surface as an error.
|
|
74
76
|
|
|
75
|
-
## Loading bundled
|
|
77
|
+
## Loading bundled pages
|
|
76
78
|
|
|
77
|
-
|
|
79
|
+
A custom-scheme URL loads like any other address:
|
|
78
80
|
|
|
79
81
|
```swift
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
@MainActor
|
|
83
|
+
func openChapter(_ name: String, in page: WebPage) async throws {
|
|
84
|
+
guard let address = URL(string: "manual://\(name)") else { return }
|
|
85
|
+
for try await _ in page.load(address) { }
|
|
82
86
|
}
|
|
83
|
-
|
|
84
87
|
```
|
|
85
88
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
## Cancellation behavior
|
|
89
|
+
Relative references inside the HTML (images, stylesheets, scripts) resolve
|
|
90
|
+
against the same scheme, so they come back through the same handler.
|
|
89
91
|
|
|
90
|
-
|
|
91
|
-
- the user navigates away
|
|
92
|
-
- the page reloads before the previous request completes
|
|
93
|
-
- the resource is no longer needed by the page
|
|
92
|
+
## Cancellation
|
|
94
93
|
|
|
95
|
-
|
|
94
|
+
WebKit stops consuming a reply when the resource is no longer wanted: the
|
|
95
|
+
user navigated away, the page reloaded, or the load became unnecessary. The
|
|
96
|
+
task producing the sequence is cancelled at that point. Treat that as a normal
|
|
97
|
+
outcome, clean up in an `onTermination` handler if you hold resources, and do
|
|
98
|
+
not assume every request runs to completion.
|
package/pipeline/skills/shared/external/swiftui-webkit/references/migration-and-fallbacks.md
CHANGED
|
@@ -1,165 +1,97 @@
|
|
|
1
|
-
# Migration and
|
|
1
|
+
# Migration and fallbacks
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
- Migration goal
|
|
5
|
-
- Decision guide
|
|
6
|
-
- Migrating from `WKWebView` wrappers
|
|
7
|
-
- Incremental migration pattern
|
|
8
|
-
- When `SFSafariViewController` is still the right choice
|
|
9
|
-
- When `ASWebAuthenticationSession` is required
|
|
10
|
-
- When `WKWebView` remains justified
|
|
11
|
-
- Testing the migration
|
|
12
|
-
- Review checklist
|
|
3
|
+
Part of the `swiftui-webkit` skill ([../SKILL.md](../SKILL.md)).
|
|
13
4
|
|
|
14
|
-
##
|
|
5
|
+
## What the migration is for
|
|
15
6
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
7
|
+
In a SwiftUI app targeting iOS 26 or later, `WebView` and `WebPage` are the
|
|
8
|
+
starting point for embedded web content. The aim is to move everyday screens
|
|
9
|
+
onto them and keep only the fallbacks that still earn their place, not to
|
|
10
|
+
delete every `WKWebView` in one sweep.
|
|
19
11
|
|
|
20
|
-
|
|
21
|
-
routine embedded web content to the new native surface and keep legacy fallback
|
|
22
|
-
paths only where they are still justified.
|
|
12
|
+
## Choosing a container
|
|
23
13
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
| Use case | Best default |
|
|
14
|
+
| Need | Choice |
|
|
27
15
|
|---|---|
|
|
28
|
-
|
|
|
16
|
+
| App-owned web content inside SwiftUI | `WebView` + `WebPage` |
|
|
29
17
|
| OAuth or third-party sign-in | `ASWebAuthenticationSession` |
|
|
30
|
-
|
|
|
31
|
-
|
|
|
32
|
-
|
|
33
|
-
## Migrating from `WKWebView` wrappers
|
|
18
|
+
| An outside site that should behave like Safari | `SFSafariViewController` |
|
|
19
|
+
| Older deployment target, or a capability the new API lacks | `WKWebView` |
|
|
34
20
|
|
|
35
|
-
|
|
36
|
-
of a `UIViewRepresentable` wrapper around `WKWebView`.
|
|
21
|
+
## Mapping the old pieces
|
|
37
22
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
| Older pattern | Modern default |
|
|
23
|
+
| `WKWebView` era | SwiftUI WebKit |
|
|
41
24
|
|---|---|
|
|
42
|
-
| `UIViewRepresentable`
|
|
43
|
-
| `WKNavigationDelegate` policy
|
|
44
|
-
| KVO
|
|
45
|
-
| `evaluateJavaScript` | `callJavaScript` |
|
|
46
|
-
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
##
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
- JS calls
|
|
62
|
-
- UI embedding
|
|
63
|
-
|
|
64
|
-
split those concerns first. Once page logic is no longer trapped inside the
|
|
65
|
-
wrapper, moving to `WebPage` gets much easier.
|
|
66
|
-
|
|
67
|
-
### Move the simplest screens first
|
|
68
|
-
|
|
69
|
-
Best first migrations:
|
|
70
|
-
|
|
71
|
-
- static help center content
|
|
72
|
-
- app-owned account or legal pages
|
|
73
|
-
- embedded flows that only need URL loading, title, and progress
|
|
74
|
-
|
|
75
|
-
Leave these for later:
|
|
76
|
-
|
|
77
|
-
- auth flows
|
|
78
|
-
- highly customized legacy UIKit screens
|
|
79
|
-
- surfaces relying on a capability you have not yet mapped to the new API set
|
|
80
|
-
|
|
81
|
-
### Keep fallback boundaries explicit
|
|
82
|
-
|
|
83
|
-
Use availability and architecture boundaries instead of mixing two approaches in
|
|
84
|
-
one view body.
|
|
25
|
+
| `UIViewRepresentable` wrapping `WKWebView` | `WebView(url:)` or `WebView(page)` |
|
|
26
|
+
| `WKNavigationDelegate` policy methods | `WebPage.NavigationDeciding` |
|
|
27
|
+
| KVO on `title`, `url`, `isLoading` | observable properties on `WebPage` |
|
|
28
|
+
| `evaluateJavaScript(_:)` | `callJavaScript(_:arguments:in:contentWorld:)` |
|
|
29
|
+
| `WKWebViewConfiguration` | `WebPage.Configuration` |
|
|
30
|
+
|
|
31
|
+
The strongest case for moving first is a SwiftUI-native app that kept a
|
|
32
|
+
`WKWebView` wrapper only because no SwiftUI view existed.
|
|
33
|
+
|
|
34
|
+
## Moving one screen at a time
|
|
35
|
+
|
|
36
|
+
1. Inside the old wrapper, separate four concerns: page state, navigation
|
|
37
|
+
policy, JavaScript calls and the view embedding.
|
|
38
|
+
2. Move the screens with the least risk first: a static help center, account
|
|
39
|
+
or legal pages the app owns, flows that only need URL, title and progress.
|
|
40
|
+
3. Leave for later: sign-in flows, heavily customised UIKit screens, and
|
|
41
|
+
anything that depends on a capability the new API does not map.
|
|
42
|
+
4. Keep remaining fallbacks in their own wrapper type instead of scattering
|
|
43
|
+
`if #available` checks through screen logic.
|
|
85
44
|
|
|
86
45
|
```swift
|
|
87
|
-
struct
|
|
88
|
-
let
|
|
46
|
+
struct EmbeddedDocument: View {
|
|
47
|
+
let address: URL
|
|
89
48
|
|
|
90
49
|
var body: some View {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
50
|
+
if #available(iOS 26.0, *) {
|
|
51
|
+
WebView(url: address)
|
|
52
|
+
} else {
|
|
53
|
+
LegacyDocumentView(address: address) // the one place WKWebView lives
|
|
54
|
+
}
|
|
95
55
|
}
|
|
96
56
|
}
|
|
97
57
|
```
|
|
98
58
|
|
|
99
|
-
|
|
100
|
-
sprinkling `if #available` checks through the screen's core logic.
|
|
101
|
-
|
|
102
|
-
## When `SFSafariViewController` is still the right choice
|
|
103
|
-
|
|
104
|
-
Use `SFSafariViewController` when the app just needs to show an external site
|
|
105
|
-
with Safari behavior and does not need page-level control.
|
|
106
|
-
|
|
107
|
-
Good fits:
|
|
108
|
-
|
|
109
|
-
- help center article from a public website
|
|
110
|
-
- a legal page or blog post
|
|
111
|
-
- a temporary browse-out flow that should keep Safari chrome and reader behavior
|
|
112
|
-
|
|
113
|
-
Do not use `SFSafariViewController` when the app needs to:
|
|
114
|
-
|
|
115
|
-
- observe page state
|
|
116
|
-
- run JavaScript
|
|
117
|
-
- intercept navigation
|
|
118
|
-
- coordinate in-app page history
|
|
119
|
-
|
|
120
|
-
## When `ASWebAuthenticationSession` is required
|
|
121
|
-
|
|
122
|
-
Use `ASWebAuthenticationSession` for OAuth and third-party sign-in.
|
|
123
|
-
|
|
124
|
-
This remains true even if the rest of the app uses `WebView` for embedded
|
|
125
|
-
content.
|
|
59
|
+
## When SFSafariViewController is still right
|
|
126
60
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
61
|
+
Use it to send people to an outside site while keeping Safari's chrome and
|
|
62
|
+
Reader: a public help article, a legal page hosted elsewhere, a blog post.
|
|
63
|
+
It is the wrong tool once the app needs page state, JavaScript, navigation
|
|
64
|
+
interception or its own history handling.
|
|
130
65
|
|
|
131
|
-
## When
|
|
66
|
+
## When ASWebAuthenticationSession is required
|
|
132
67
|
|
|
133
|
-
|
|
68
|
+
Every OAuth or third-party sign-in flow goes through it, even when the rest
|
|
69
|
+
of the feature uses `WebView`. The `authentication` skill covers the flow
|
|
70
|
+
itself.
|
|
134
71
|
|
|
135
|
-
|
|
136
|
-
- the codebase is still UIKit-first and not ready to move the surface into
|
|
137
|
-
native SwiftUI WebKit APIs
|
|
138
|
-
- a required legacy-only WebKit capability is not yet available through the new
|
|
139
|
-
SwiftUI-facing API surface
|
|
140
|
-
- a heavily customized existing surface would create churn without product value
|
|
72
|
+
## When WKWebView still makes sense
|
|
141
73
|
|
|
142
|
-
|
|
143
|
-
|
|
74
|
+
- the deployment target is below iOS 26
|
|
75
|
+
- a UIKit-first codebase is not ready to move
|
|
76
|
+
- a capability exists only on the old API
|
|
77
|
+
- the screen is so customised that migrating it costs more than it returns
|
|
144
78
|
|
|
145
|
-
|
|
79
|
+
Keep such cases as a conscious fallback, documented where the wrapper lives.
|
|
146
80
|
|
|
147
|
-
|
|
81
|
+
## Testing a migrated screen
|
|
148
82
|
|
|
149
|
-
-
|
|
150
|
-
- JavaScript calls
|
|
151
|
-
-
|
|
152
|
-
-
|
|
153
|
-
-
|
|
154
|
-
|
|
155
|
-
- fallback `WKWebView` screens stay isolated instead of spreading wrapper logic
|
|
156
|
-
back into new screens
|
|
83
|
+
- Title and URL update as the user navigates.
|
|
84
|
+
- JavaScript calls reach the page and their results decode.
|
|
85
|
+
- Policy decisions match the old delegate (same links stay in, same links leave).
|
|
86
|
+
- Loading and error states appear at the right moments.
|
|
87
|
+
- No sign-in flow ended up inside the embedded view.
|
|
88
|
+
- Fallback wrappers are still confined to their own types.
|
|
157
89
|
|
|
158
|
-
##
|
|
90
|
+
## Checklist
|
|
159
91
|
|
|
160
|
-
- [ ] New
|
|
161
|
-
- [ ] `SFSafariViewController` used only for browse-out
|
|
162
|
-
- [ ] `ASWebAuthenticationSession`
|
|
163
|
-
- [ ] `WKWebView`
|
|
164
|
-
- [ ]
|
|
165
|
-
- [ ] No new iOS 26+ feature
|
|
92
|
+
- [ ] New screens start with `WebView` and `WebPage`
|
|
93
|
+
- [ ] `SFSafariViewController` is used only for browse-out
|
|
94
|
+
- [ ] Sign-in stays on `ASWebAuthenticationSession`
|
|
95
|
+
- [ ] `WKWebView` appears only where one of the reasons above applies
|
|
96
|
+
- [ ] Fallbacks live in dedicated wrapper types
|
|
97
|
+
- [ ] No new iOS 26+ feature begins life as a `UIViewRepresentable` web view wrapper
|
package/pipeline/skills/shared/external/swiftui-webkit/references/navigation-and-javascript.md
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
# Navigation and JavaScript
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
- Navigation policy decisions
|
|
5
|
-
- Opening external links outside the embedded web view
|
|
6
|
-
- Calling JavaScript
|
|
7
|
-
- Passing arguments into JavaScript
|
|
8
|
-
- Coarse JS-to-native signaling
|
|
3
|
+
Part of the `swiftui-webkit` skill ([../SKILL.md](../SKILL.md)).
|
|
9
4
|
|
|
10
|
-
##
|
|
5
|
+
## An observable navigation decider
|
|
11
6
|
|
|
12
|
-
|
|
7
|
+
Making the decider itself `@Observable` lets a view react when it cancels a
|
|
8
|
+
navigation that should leave the app.
|
|
13
9
|
|
|
14
10
|
```swift
|
|
15
11
|
import Observation
|
|
@@ -17,95 +13,127 @@ import WebKit
|
|
|
17
13
|
|
|
18
14
|
@Observable
|
|
19
15
|
@MainActor
|
|
20
|
-
final class
|
|
21
|
-
var
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
guard let
|
|
28
|
-
|
|
29
|
-
if
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
urlToOpenExternally = url
|
|
16
|
+
final class LinkPolicy: WebPage.NavigationDeciding {
|
|
17
|
+
var outboundURL: URL?
|
|
18
|
+
private let ownedHosts: Set<String> = ["support.example.net", "status.example.net"]
|
|
19
|
+
|
|
20
|
+
func decidePolicy(for step: WebPage.NavigationAction,
|
|
21
|
+
preferences prefs: inout WebPage.NavigationPreferences)
|
|
22
|
+
async -> WKNavigationActionPolicy {
|
|
23
|
+
guard let target = step.request.url else { return .allow }
|
|
24
|
+
if let host = target.host(), ownedHosts.contains(host) { return .allow }
|
|
25
|
+
if target.scheme == "about" { return .allow }
|
|
26
|
+
outboundURL = target
|
|
34
27
|
return .cancel
|
|
35
28
|
}
|
|
36
29
|
}
|
|
37
30
|
```
|
|
38
31
|
|
|
39
|
-
|
|
32
|
+
## Sending outside links to the system
|
|
40
33
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
Bridge the decider back into SwiftUI with `openURL`.
|
|
34
|
+
Build the decider and the page once, in `init`, then open whatever the
|
|
35
|
+
decider rejected with the environment's `openURL`.
|
|
44
36
|
|
|
45
37
|
```swift
|
|
46
|
-
|
|
38
|
+
import SwiftUI
|
|
39
|
+
import WebKit
|
|
40
|
+
|
|
41
|
+
struct SupportScreen: View {
|
|
47
42
|
@Environment(\.openURL) private var openURL
|
|
48
|
-
@State private var
|
|
43
|
+
@State private var policy: LinkPolicy
|
|
49
44
|
@State private var page: WebPage
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
45
|
+
let entry: URL
|
|
46
|
+
|
|
47
|
+
init(entry: URL) {
|
|
48
|
+
self.entry = entry
|
|
49
|
+
let policy = LinkPolicy()
|
|
50
|
+
_policy = State(wrappedValue: policy)
|
|
51
|
+
let setup = WebPage.Configuration()
|
|
52
|
+
_page = State(wrappedValue: WebPage(configuration: setup, navigationDecider: policy))
|
|
55
53
|
}
|
|
56
54
|
|
|
57
55
|
var body: some View {
|
|
58
56
|
WebView(page)
|
|
59
|
-
.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
57
|
+
.task { _ = page.load(entry) }
|
|
58
|
+
.onChange(of: policy.outboundURL) { _, destination in
|
|
59
|
+
guard let destination else { return }
|
|
60
|
+
openURL(destination)
|
|
61
|
+
policy.outboundURL = nil
|
|
63
62
|
}
|
|
64
63
|
}
|
|
65
64
|
}
|
|
66
65
|
```
|
|
67
66
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
## Calling JavaScript
|
|
67
|
+
## Running JavaScript
|
|
71
68
|
|
|
72
|
-
`callJavaScript`
|
|
69
|
+
The string passed to `callJavaScript` becomes the body of an async function,
|
|
70
|
+
and whatever it returns comes back as `Any?`. Convert it to the structure you
|
|
71
|
+
expect immediately so the rest of the code stays typed.
|
|
73
72
|
|
|
74
73
|
```swift
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
title: node.textContent?.trim()
|
|
80
|
-
}));
|
|
81
|
-
"""
|
|
82
|
-
|
|
83
|
-
let result = try await page.callJavaScript(script)
|
|
84
|
-
let headings = result as? [[String: Any]] ?? []
|
|
85
|
-
```
|
|
74
|
+
struct Outline {
|
|
75
|
+
let anchor: String
|
|
76
|
+
let label: String
|
|
77
|
+
}
|
|
86
78
|
|
|
87
|
-
|
|
79
|
+
@MainActor
|
|
80
|
+
func readOutline(of page: WebPage) async throws -> [Outline] {
|
|
81
|
+
let outcome = try await page.callJavaScript("""
|
|
82
|
+
return Array.from(document.querySelectorAll('h2[id]'), el => ({ anchor: el.id, label: el.innerText }));
|
|
83
|
+
""")
|
|
84
|
+
guard let rows = outcome as? [[String: Any]] else { return [] }
|
|
85
|
+
return rows.compactMap { row in
|
|
86
|
+
guard let anchor = row["anchor"] as? String, let label = row["label"] as? String else { return nil }
|
|
87
|
+
return Outline(anchor: anchor, label: label)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
88
91
|
|
|
89
|
-
##
|
|
92
|
+
## Handing values to the script
|
|
90
93
|
|
|
91
|
-
|
|
94
|
+
Every key of the `arguments` dictionary turns into a local variable of that function. This is the
|
|
95
|
+
safe way to feed in user text or other untrusted values; never splice them
|
|
96
|
+
into the script string.
|
|
92
97
|
|
|
93
98
|
```swift
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
)
|
|
99
|
+
@MainActor
|
|
100
|
+
func highlightCount(of term: String, in page: WebPage) async throws -> Int {
|
|
101
|
+
let found = try await page.callJavaScript(
|
|
102
|
+
"return (document.body.innerText.match(new RegExp(needle, 'gi')) || []).length;",
|
|
103
|
+
arguments: ["needle": NSRegularExpression.escapedPattern(for: term)]
|
|
104
|
+
)
|
|
105
|
+
return (found as? Double).map(Int.init) ?? 0
|
|
106
|
+
}
|
|
98
107
|
```
|
|
99
108
|
|
|
100
|
-
|
|
109
|
+
JavaScript numbers arrive as `Double` (or `NSNumber`), so cast accordingly.
|
|
110
|
+
|
|
111
|
+
## Simple signals from the page to the app
|
|
101
112
|
|
|
102
|
-
|
|
113
|
+
For a one-bit message such as "the form is done", the page can navigate to a
|
|
114
|
+
custom URL that the decider recognises, reads and cancels:
|
|
103
115
|
|
|
104
|
-
|
|
116
|
+
```javascript
|
|
117
|
+
window.location.href = "app-event://checkout-finished?order=A1942";
|
|
118
|
+
```
|
|
105
119
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
120
|
+
```swift
|
|
121
|
+
@MainActor
|
|
122
|
+
final class CheckoutWatcher: WebPage.NavigationDeciding {
|
|
123
|
+
var finishedOrder: String?
|
|
124
|
+
|
|
125
|
+
func decidePolicy(for step: WebPage.NavigationAction,
|
|
126
|
+
preferences prefs: inout WebPage.NavigationPreferences)
|
|
127
|
+
async -> WKNavigationActionPolicy {
|
|
128
|
+
guard let target = step.request.url, target.scheme == "app-event" else { return .allow }
|
|
129
|
+
let parts = URLComponents(url: target, resolvingAgainstBaseURL: false)
|
|
130
|
+
finishedOrder = parts?.queryItems?.first { $0.name == "order" }?.value
|
|
131
|
+
return .cancel
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
110
135
|
|
|
111
|
-
|
|
136
|
+
Keep this to simple completion or routing signals. It is not a structured
|
|
137
|
+
substitute for script message handlers registered on a
|
|
138
|
+
`WKUserContentController`; when you need real two-way messaging, use the
|
|
139
|
+
`userContentController` that `WebPage.Configuration` exposes.
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name: tailwind-css
|
|
3
3
|
description: "Tailwind CSS v4: utility-first styling, responsive design, dark mode, custom themes, component patterns, and cn() utility. Use when styling or reviewing UI with Tailwind: utilities, responsive design, dark mode, theming."
|
|
4
4
|
metadata:
|
|
5
|
+
source: multi-agent-pipeline
|
|
5
6
|
tags: [tailwind, css, styling, responsive, dark-mode, frontend]
|
|
6
7
|
version: "2025.1"
|
|
7
8
|
---
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name: testing-backend
|
|
3
3
|
description: "Backend testing: pytest patterns (Python), Jest patterns (Node.js), integration testing, database fixtures/factories, API contract testing. Use when writing or reviewing backend tests: unit, integration, database and API level."
|
|
4
4
|
metadata:
|
|
5
|
+
source: multi-agent-pipeline
|
|
5
6
|
tags: [testing, pytest, jest, integration, database, api-testing, backend]
|
|
6
7
|
version: "2025.1"
|
|
7
8
|
---
|