@swiftbrowser/swift 0.0.0-stage → 0.2.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.
Files changed (400) hide show
  1. package/Package.swift +214 -0
  2. package/README.md +10 -2
  3. package/Sources/AVFoundation/AVFoundation.swift +131 -0
  4. package/Sources/AVFoundation/Asset.swift +487 -0
  5. package/Sources/AVFoundation/AudioSession.swift +144 -0
  6. package/Sources/AVFoundation/CMTime.swift +303 -0
  7. package/Sources/AVFoundation/Capture.swift +688 -0
  8. package/Sources/AVFoundation/Player.swift +749 -0
  9. package/Sources/AVFoundation/PlayerView.swift +117 -0
  10. package/Sources/AVKit/AVKit.swift +132 -0
  11. package/Sources/Accelerate/Accelerate.swift +122 -0
  12. package/Sources/AppIntents/AppIntents.swift +144 -0
  13. package/Sources/AppIntents/Parameters.swift +220 -0
  14. package/Sources/AppIntents/Shortcuts.swift +159 -0
  15. package/Sources/AudioToolbox/AudioToolbox.swift +55 -0
  16. package/Sources/AuthenticationServices/AuthenticationServices.swift +257 -0
  17. package/Sources/AuthenticationServices/Authorization.swift +251 -0
  18. package/Sources/Charts/Charts.swift +61 -0
  19. package/Sources/Combine/AnyCancellable.swift +65 -0
  20. package/Sources/Combine/AnyPublisher.swift +148 -0
  21. package/Sources/Combine/AnySubscriber.swift +230 -0
  22. package/Sources/Combine/Cancellable.swift +35 -0
  23. package/Sources/Combine/Codable.swift +29 -0
  24. package/Sources/Combine/CombineIdentifier.swift +45 -0
  25. package/Sources/Combine/Concurrency/ConcurrencyHelpers.swift +24 -0
  26. package/Sources/Combine/Concurrency/Future+Concurrency.swift +136 -0
  27. package/Sources/Combine/Concurrency/GENERATED-Publisher+Concurrency.swift +397 -0
  28. package/Sources/Combine/CurrentValueSubject.swift +252 -0
  29. package/Sources/Combine/CustomCombineIdentifierConvertible.swift +28 -0
  30. package/Sources/Combine/Future.swift +228 -0
  31. package/Sources/Combine/GENERATED-RootProtocols.swift +426 -0
  32. package/Sources/Combine/Helpers/ConduitBase.swift +40 -0
  33. package/Sources/Combine/Helpers/ConduitList.swift +59 -0
  34. package/Sources/Combine/Helpers/DebugHook.swift +177 -0
  35. package/Sources/Combine/Helpers/FilterProducer.swift +174 -0
  36. package/Sources/Combine/Helpers/Locking.swift +30 -0
  37. package/Sources/Combine/Helpers/PartialCompletion.swift +26 -0
  38. package/Sources/Combine/Helpers/ReduceProducer.swift +249 -0
  39. package/Sources/Combine/Helpers/SubjectSubscriber.swift +96 -0
  40. package/Sources/Combine/Helpers/SubscriberTap.swift +69 -0
  41. package/Sources/Combine/Helpers/SubscriptionStatus.swift +33 -0
  42. package/Sources/Combine/Helpers/SubscriptionTap.swift +33 -0
  43. package/Sources/Combine/Helpers/Utils.swift +30 -0
  44. package/Sources/Combine/Helpers/Violations.swift +33 -0
  45. package/Sources/Combine/ImmediateScheduler.swift +178 -0
  46. package/Sources/Combine/LICENSE +21 -0
  47. package/Sources/Combine/NotificationPublisher.swift +48 -0
  48. package/Sources/Combine/ObjectWillChange.swift +46 -0
  49. package/Sources/Combine/PassthroughSubject.swift +222 -0
  50. package/Sources/Combine/Publisher+Subscribe.swift +53 -0
  51. package/Sources/Combine/Publishers/Deferred.swift +48 -0
  52. package/Sources/Combine/Publishers/Empty.swift +54 -0
  53. package/Sources/Combine/Publishers/Fail.swift +42 -0
  54. package/Sources/Combine/Publishers/GENERATED-Publishers.Catch.swift +673 -0
  55. package/Sources/Combine/Publishers/GENERATED-Publishers.Encode.swift +388 -0
  56. package/Sources/Combine/Publishers/GENERATED-Publishers.MapKeyPath.swift +384 -0
  57. package/Sources/Combine/Publishers/Just.swift +313 -0
  58. package/Sources/Combine/Publishers/Optional.Publisher.swift +315 -0
  59. package/Sources/Combine/Publishers/Publishers.AllSatisfy.swift +217 -0
  60. package/Sources/Combine/Publishers/Publishers.AssertNoFailure.swift +158 -0
  61. package/Sources/Combine/Publishers/Publishers.Autoconnect.swift +193 -0
  62. package/Sources/Combine/Publishers/Publishers.Breakpoint.swift +231 -0
  63. package/Sources/Combine/Publishers/Publishers.Buffer.swift +356 -0
  64. package/Sources/Combine/Publishers/Publishers.Collect.swift +102 -0
  65. package/Sources/Combine/Publishers/Publishers.CollectByCount.swift +195 -0
  66. package/Sources/Combine/Publishers/Publishers.CompactMap.swift +241 -0
  67. package/Sources/Combine/Publishers/Publishers.Comparison.swift +371 -0
  68. package/Sources/Combine/Publishers/Publishers.Concatenate.swift +474 -0
  69. package/Sources/Combine/Publishers/Publishers.Contains.swift +293 -0
  70. package/Sources/Combine/Publishers/Publishers.Count.swift +87 -0
  71. package/Sources/Combine/Publishers/Publishers.Debounce.swift +332 -0
  72. package/Sources/Combine/Publishers/Publishers.Delay.swift +269 -0
  73. package/Sources/Combine/Publishers/Publishers.Drop.swift +155 -0
  74. package/Sources/Combine/Publishers/Publishers.DropUntilOutput.swift +283 -0
  75. package/Sources/Combine/Publishers/Publishers.DropWhile.swift +378 -0
  76. package/Sources/Combine/Publishers/Publishers.Filter.swift +248 -0
  77. package/Sources/Combine/Publishers/Publishers.First.swift +261 -0
  78. package/Sources/Combine/Publishers/Publishers.FlatMap.swift +533 -0
  79. package/Sources/Combine/Publishers/Publishers.HandleEvents.swift +260 -0
  80. package/Sources/Combine/Publishers/Publishers.IgnoreOutput.swift +109 -0
  81. package/Sources/Combine/Publishers/Publishers.Last.swift +252 -0
  82. package/Sources/Combine/Publishers/Publishers.MakeConnectable.swift +82 -0
  83. package/Sources/Combine/Publishers/Publishers.Map.swift +351 -0
  84. package/Sources/Combine/Publishers/Publishers.MapError.swift +140 -0
  85. package/Sources/Combine/Publishers/Publishers.MeasureInterval.swift +187 -0
  86. package/Sources/Combine/Publishers/Publishers.Multicast.swift +284 -0
  87. package/Sources/Combine/Publishers/Publishers.Output.swift +241 -0
  88. package/Sources/Combine/Publishers/Publishers.PrefixUntilOutput.swift +197 -0
  89. package/Sources/Combine/Publishers/Publishers.PrefixWhile.swift +176 -0
  90. package/Sources/Combine/Publishers/Publishers.Print.swift +206 -0
  91. package/Sources/Combine/Publishers/Publishers.ReceiveOn.swift +227 -0
  92. package/Sources/Combine/Publishers/Publishers.Reduce.swift +204 -0
  93. package/Sources/Combine/Publishers/Publishers.RemoveDuplicates.swift +264 -0
  94. package/Sources/Combine/Publishers/Publishers.ReplaceEmpty.swift +201 -0
  95. package/Sources/Combine/Publishers/Publishers.ReplaceError.swift +211 -0
  96. package/Sources/Combine/Publishers/Publishers.Retry.swift +274 -0
  97. package/Sources/Combine/Publishers/Publishers.Scan.swift +331 -0
  98. package/Sources/Combine/Publishers/Publishers.Sequence.swift +437 -0
  99. package/Sources/Combine/Publishers/Publishers.SetFailureType.swift +120 -0
  100. package/Sources/Combine/Publishers/Publishers.Share.swift +104 -0
  101. package/Sources/Combine/Publishers/Publishers.SubscribeOn.swift +197 -0
  102. package/Sources/Combine/Publishers/Publishers.SwitchToLatest.swift +444 -0
  103. package/Sources/Combine/Publishers/Publishers.Throttle.swift +359 -0
  104. package/Sources/Combine/Publishers/Publishers.Timeout.swift +301 -0
  105. package/Sources/Combine/Publishers/Publishers.Zip.swift +720 -0
  106. package/Sources/Combine/Publishers/Publishers.swift +13 -0
  107. package/Sources/Combine/Publishers/Record.swift +237 -0
  108. package/Sources/Combine/Publishers/Result.Publisher.swift +337 -0
  109. package/Sources/Combine/Result.swift +46 -0
  110. package/Sources/Combine/Scheduler.swift +89 -0
  111. package/Sources/Combine/Schedulers.swift +211 -0
  112. package/Sources/Combine/Subject+Void.swift +17 -0
  113. package/Sources/Combine/Subscriber+Void.swift +20 -0
  114. package/Sources/Combine/Subscribers/Subscribers.Assign.swift +175 -0
  115. package/Sources/Combine/Subscribers/Subscribers.Completion.swift +90 -0
  116. package/Sources/Combine/Subscribers/Subscribers.Demand.swift +476 -0
  117. package/Sources/Combine/Subscribers/Subscribers.Sink.swift +206 -0
  118. package/Sources/Combine/Subscribers/Subscribers.swift +9 -0
  119. package/Sources/Combine/Subscription.swift +22 -0
  120. package/Sources/Combine/Subscriptions.swift +42 -0
  121. package/Sources/Combine/SwiftUIObservation.swift +10 -0
  122. package/Sources/Combine/_Introspection.swift +107 -0
  123. package/Sources/CommonCrypto/CommonCrypto.swift +80 -0
  124. package/Sources/Compression/Compression.swift +365 -0
  125. package/Sources/Compression/Deflate.swift +407 -0
  126. package/Sources/Compression/Zlib.swift +179 -0
  127. package/Sources/CoreFoundationTypes/CoreFoundationTypes.swift +101 -0
  128. package/Sources/CoreGraphics/CoreGraphics.swift +411 -0
  129. package/Sources/CoreGraphics/ProjectionTransforms.swift +28 -0
  130. package/Sources/CoreHaptics/CoreHaptics.swift +399 -0
  131. package/Sources/CoreImage/CIColor.swift +41 -0
  132. package/Sources/CoreImage/CIContext.swift +31 -0
  133. package/Sources/CoreImage/CIDetector.swift +57 -0
  134. package/Sources/CoreImage/CIFilter.swift +243 -0
  135. package/Sources/CoreImage/CIFilterBuiltins.swift +136 -0
  136. package/Sources/CoreImage/CIImage.swift +162 -0
  137. package/Sources/CoreImage/QRCode.swift +393 -0
  138. package/Sources/CoreLocation/Coordinate.swift +30 -0
  139. package/Sources/CoreLocation/Location.swift +65 -0
  140. package/Sources/CoreML/Evaluation.swift +414 -0
  141. package/Sources/CoreML/FeatureValue.swift +266 -0
  142. package/Sources/CoreML/Model.swift +269 -0
  143. package/Sources/CoreML/MultiArray.swift +92 -0
  144. package/Sources/CoreML/Specification.swift +233 -0
  145. package/Sources/CoreText/CoreText.swift +64 -0
  146. package/Sources/CoreTransferable/CoreTransferable.swift +606 -0
  147. package/Sources/CryptoKit/ChaChaPoly.swift +258 -0
  148. package/Sources/CryptoKit/CryptoKit.swift +375 -0
  149. package/Sources/CryptoKit/Curve25519.swift +317 -0
  150. package/Sources/CryptoKit/P256.swift +321 -0
  151. package/Sources/FoundationBridge/AppStorage.swift +165 -0
  152. package/Sources/FoundationBridge/AssetResources.swift +90 -0
  153. package/Sources/FoundationBridge/AsyncBytes.swift +128 -0
  154. package/Sources/FoundationBridge/AsyncImage.swift +116 -0
  155. package/Sources/FoundationBridge/AttributedStrings.swift +16 -0
  156. package/Sources/FoundationBridge/Bundle.swift +119 -0
  157. package/Sources/FoundationBridge/CombineExports.swift +8 -0
  158. package/Sources/FoundationBridge/CoreFoundation.swift +77 -0
  159. package/Sources/FoundationBridge/Dispatch.swift +458 -0
  160. package/Sources/FoundationBridge/EnvironmentFoundation.swift +41 -0
  161. package/Sources/FoundationBridge/FileImporter.swift +128 -0
  162. package/Sources/FoundationBridge/FileSystem.swift +68 -0
  163. package/Sources/FoundationBridge/FoundationBridge.swift +29 -0
  164. package/Sources/FoundationBridge/HostResolution.swift +31 -0
  165. package/Sources/FoundationBridge/ItemProvider.swift +655 -0
  166. package/Sources/FoundationBridge/KeyValueObserving.swift +138 -0
  167. package/Sources/FoundationBridge/Links.swift +127 -0
  168. package/Sources/FoundationBridge/ListFormatter.swift +32 -0
  169. package/Sources/FoundationBridge/Locale.swift +86 -0
  170. package/Sources/FoundationBridge/Localization.swift +149 -0
  171. package/Sources/FoundationBridge/Locks.swift +50 -0
  172. package/Sources/FoundationBridge/Markdown.swift +527 -0
  173. package/Sources/FoundationBridge/MeasurementFormat.swift +95 -0
  174. package/Sources/FoundationBridge/NotificationCenter.swift +154 -0
  175. package/Sources/FoundationBridge/OpenURLHandlers.swift +60 -0
  176. package/Sources/FoundationBridge/Operation.swift +195 -0
  177. package/Sources/FoundationBridge/ProcessInfo.swift +32 -0
  178. package/Sources/FoundationBridge/RelativeDateTimeFormatter.swift +136 -0
  179. package/Sources/FoundationBridge/SceneStorage.swift +78 -0
  180. package/Sources/FoundationBridge/SecurityExports.swift +8 -0
  181. package/Sources/FoundationBridge/Selector.swift +226 -0
  182. package/Sources/FoundationBridge/StringComparators.swift +17 -0
  183. package/Sources/FoundationBridge/Table.swift +211 -0
  184. package/Sources/FoundationBridge/TextAttributes.swift +42 -0
  185. package/Sources/FoundationBridge/Timer.swift +53 -0
  186. package/Sources/FoundationBridge/UITextChecker.swift +30 -0
  187. package/Sources/FoundationBridge/URLSession.swift +718 -0
  188. package/Sources/FoundationBridge/UserDefaults.swift +183 -0
  189. package/Sources/FoundationBridge/WebAuthRedirects.swift +227 -0
  190. package/Sources/FoundationBridge/WebSocket.swift +187 -0
  191. package/Sources/FoundationModels/FoundationModels.swift +1098 -0
  192. package/Sources/ImageIO/GIF.swift +72 -0
  193. package/Sources/ImageIO/ImageIO.swift +248 -0
  194. package/Sources/ImageIO/ImageTypes.swift +28 -0
  195. package/Sources/LinkPresentation/LinkPresentation.swift +249 -0
  196. package/Sources/LocalAuthentication/LAContext.swift +86 -0
  197. package/Sources/MapKit/Geometry.swift +223 -0
  198. package/Sources/MapKit/Map.swift +638 -0
  199. package/Sources/MapKit/MapView.swift +229 -0
  200. package/Sources/MobileCoreServices/MobileCoreServices.swift +28 -0
  201. package/Sources/NaturalLanguage/LanguageIdentifier.swift +317 -0
  202. package/Sources/NaturalLanguage/NaturalLanguage.swift +135 -0
  203. package/Sources/OSLog/OSLog.swift +6 -0
  204. package/Sources/Photos/Photos.swift +572 -0
  205. package/Sources/PhotosUI/PhotosPicker.swift +248 -0
  206. package/Sources/PhotosUI/PhotosPickerItem.swift +261 -0
  207. package/Sources/QuickLook/QuickLook.swift +168 -0
  208. package/Sources/SafariServices/SafariServices.swift +106 -0
  209. package/Sources/Security/Security.swift +332 -0
  210. package/Sources/StoreKit/AppStore.swift +207 -0
  211. package/Sources/StoreKit/Products.swift +280 -0
  212. package/Sources/StoreKit/RequestReview.swift +28 -0
  213. package/Sources/StoreKit/StoreKit1.swift +486 -0
  214. package/Sources/StoreKit/StoreViews.swift +428 -0
  215. package/Sources/StoreKit/Transactions.swift +197 -0
  216. package/Sources/SwiftData/Macros.swift +58 -0
  217. package/Sources/SwiftData/ModelActor.swift +38 -0
  218. package/Sources/SwiftData/ModelContainer.swift +129 -0
  219. package/Sources/SwiftData/ModelContext.swift +451 -0
  220. package/Sources/SwiftData/PersistentModel.swift +238 -0
  221. package/Sources/SwiftData/Properties.swift +261 -0
  222. package/Sources/SwiftData/Query.swift +256 -0
  223. package/Sources/SwiftData/Schema.swift +192 -0
  224. package/Sources/SwiftData/Store.swift +146 -0
  225. package/Sources/SwiftData/StringPredicates.swift +125 -0
  226. package/Sources/SwiftDataMacros/EntryMacro.swift +82 -0
  227. package/Sources/SwiftDataMacros/GenerableMacro.swift +183 -0
  228. package/Sources/SwiftDataMacros/ModelActorMacro.swift +46 -0
  229. package/Sources/SwiftDataMacros/ModelMacro.swift +260 -0
  230. package/Sources/SwiftDataMacros/Plugin.swift +18 -0
  231. package/Sources/SwiftDataMacros/PredicateMacro.swift +1244 -0
  232. package/Sources/SwiftUI/API/Accessibility.swift +181 -0
  233. package/Sources/SwiftUI/API/AccessibilityExtras.swift +33 -0
  234. package/Sources/SwiftUI/API/AccessibilityFocus.swift +63 -0
  235. package/Sources/SwiftUI/API/Alert.swift +221 -0
  236. package/Sources/SwiftUI/API/AlignmentGuides.swift +65 -0
  237. package/Sources/SwiftUI/API/Animation.swift +285 -0
  238. package/Sources/SwiftUI/API/App.swift +87 -0
  239. package/Sources/SwiftUI/API/BindingCollections.swift +35 -0
  240. package/Sources/SwiftUI/API/BindingForEach.swift +27 -0
  241. package/Sources/SwiftUI/API/Bitmaps.swift +254 -0
  242. package/Sources/SwiftUI/API/ButtonStyles.swift +96 -0
  243. package/Sources/SwiftUI/API/Canvas.swift +337 -0
  244. package/Sources/SwiftUI/API/Color.swift +237 -0
  245. package/Sources/SwiftUI/API/ColorEffects.swift +52 -0
  246. package/Sources/SwiftUI/API/ColorPickerAndLabeledContent.swift +138 -0
  247. package/Sources/SwiftUI/API/ColorSpaces.swift +161 -0
  248. package/Sources/SwiftUI/API/Commands.swift +106 -0
  249. package/Sources/SwiftUI/API/ContainerBackground.swift +28 -0
  250. package/Sources/SwiftUI/API/ContentShape.swift +33 -0
  251. package/Sources/SwiftUI/API/ContentSizeCategory.swift +35 -0
  252. package/Sources/SwiftUI/API/ContentUnavailable.swift +101 -0
  253. package/Sources/SwiftUI/API/Controls.swift +300 -0
  254. package/Sources/SwiftUI/API/CustomLayout.swift +442 -0
  255. package/Sources/SwiftUI/API/CustomToolbarContent.swift +46 -0
  256. package/Sources/SwiftUI/API/Decorations.swift +92 -0
  257. package/Sources/SwiftUI/API/EditMode.swift +212 -0
  258. package/Sources/SwiftUI/API/Effects.swift +388 -0
  259. package/Sources/SwiftUI/API/Entry.swift +8 -0
  260. package/Sources/SwiftUI/API/Environment.swift +439 -0
  261. package/Sources/SwiftUI/API/EnvironmentSendable.swift +6 -0
  262. package/Sources/SwiftUI/API/Focus.swift +137 -0
  263. package/Sources/SwiftUI/API/Font.swift +131 -0
  264. package/Sources/SwiftUI/API/Gauge.swift +290 -0
  265. package/Sources/SwiftUI/API/Geometry.swift +89 -0
  266. package/Sources/SwiftUI/API/GeometryEffects.swift +232 -0
  267. package/Sources/SwiftUI/API/GeometryReader.swift +135 -0
  268. package/Sources/SwiftUI/API/GestureState.swift +65 -0
  269. package/Sources/SwiftUI/API/Gestures.swift +342 -0
  270. package/Sources/SwiftUI/API/Glass.swift +127 -0
  271. package/Sources/SwiftUI/API/Grid.swift +188 -0
  272. package/Sources/SwiftUI/API/GroupBoxAndControlGroup.swift +130 -0
  273. package/Sources/SwiftUI/API/KeyPress.swift +54 -0
  274. package/Sources/SwiftUI/API/LabelStyle.swift +124 -0
  275. package/Sources/SwiftUI/API/Layout.swift +220 -0
  276. package/Sources/SwiftUI/API/LazyStacks.swift +49 -0
  277. package/Sources/SwiftUI/API/LegacyAlert.swift +97 -0
  278. package/Sources/SwiftUI/API/Lists.swift +331 -0
  279. package/Sources/SwiftUI/API/Menu.swift +58 -0
  280. package/Sources/SwiftUI/API/Modifiers.swift +313 -0
  281. package/Sources/SwiftUI/API/MoreModifiers.swift +100 -0
  282. package/Sources/SwiftUI/API/Namespace.swift +44 -0
  283. package/Sources/SwiftUI/API/Navigation.swift +386 -0
  284. package/Sources/SwiftUI/API/NavigationDestinationBindings.swift +55 -0
  285. package/Sources/SwiftUI/API/ObservableObject.swift +293 -0
  286. package/Sources/SwiftUI/API/OnChange.swift +48 -0
  287. package/Sources/SwiftUI/API/Path.swift +543 -0
  288. package/Sources/SwiftUI/API/Phase8Controls.swift +411 -0
  289. package/Sources/SwiftUI/API/PhaseAnimator.swift +130 -0
  290. package/Sources/SwiftUI/API/Picker.swift +185 -0
  291. package/Sources/SwiftUI/API/PointerAndKeyboard.swift +77 -0
  292. package/Sources/SwiftUI/API/Popover.swift +41 -0
  293. package/Sources/SwiftUI/API/Preferences.swift +262 -0
  294. package/Sources/SwiftUI/API/Presentation.swift +122 -0
  295. package/Sources/SwiftUI/API/PresentationExtras.swift +60 -0
  296. package/Sources/SwiftUI/API/Primitives.swift +517 -0
  297. package/Sources/SwiftUI/API/Publishers.swift +107 -0
  298. package/Sources/SwiftUI/API/Redaction.swift +75 -0
  299. package/Sources/SwiftUI/API/RowActions.swift +84 -0
  300. package/Sources/SwiftUI/API/Scenes.swift +131 -0
  301. package/Sources/SwiftUI/API/ScrollModifiers.swift +132 -0
  302. package/Sources/SwiftUI/API/ScrollTargets.swift +104 -0
  303. package/Sources/SwiftUI/API/ScrollViewReader.swift +144 -0
  304. package/Sources/SwiftUI/API/SectionSupplements.swift +96 -0
  305. package/Sources/SwiftUI/API/Shape.swift +214 -0
  306. package/Sources/SwiftUI/API/ShapeStyle.swift +409 -0
  307. package/Sources/SwiftUI/API/ShapeTrim.swift +78 -0
  308. package/Sources/SwiftUI/API/Sharing.swift +193 -0
  309. package/Sources/SwiftUI/API/StackLayouts.swift +199 -0
  310. package/Sources/SwiftUI/API/State.swift +144 -0
  311. package/Sources/SwiftUI/API/StatusGaps.swift +121 -0
  312. package/Sources/SwiftUI/API/StrokeStyle.swift +30 -0
  313. package/Sources/SwiftUI/API/SymbolEffects.swift +203 -0
  314. package/Sources/SwiftUI/API/TabContent.swift +841 -0
  315. package/Sources/SwiftUI/API/Table.swift +382 -0
  316. package/Sources/SwiftUI/API/Tabs.swift +263 -0
  317. package/Sources/SwiftUI/API/Tasks.swift +35 -0
  318. package/Sources/SwiftUI/API/Text.swift +386 -0
  319. package/Sources/SwiftUI/API/TextDates.swift +61 -0
  320. package/Sources/SwiftUI/API/TextDecorations.swift +52 -0
  321. package/Sources/SwiftUI/API/TextFieldAxis.swift +103 -0
  322. package/Sources/SwiftUI/API/TextFieldCommit.swift +52 -0
  323. package/Sources/SwiftUI/API/Timeline.swift +212 -0
  324. package/Sources/SwiftUI/API/Toolbar.swift +251 -0
  325. package/Sources/SwiftUI/API/Transfer.swift +145 -0
  326. package/Sources/SwiftUI/API/UnevenRoundedRectangle.swift +66 -0
  327. package/Sources/SwiftUI/API/Video.swift +64 -0
  328. package/Sources/SwiftUI/API/View.swift +215 -0
  329. package/Sources/SwiftUI/API/ViewModifier.swift +43 -0
  330. package/Sources/SwiftUI/API/VisualEffect.swift +155 -0
  331. package/Sources/SwiftUI/API/Windows.swift +25 -0
  332. package/Sources/SwiftUI/Charts/Axis.swift +325 -0
  333. package/Sources/SwiftUI/Charts/AxisFormatsAndRanges.swift +68 -0
  334. package/Sources/SwiftUI/Charts/Chart.swift +660 -0
  335. package/Sources/SwiftUI/Charts/ChartContent.swift +376 -0
  336. package/Sources/SwiftUI/Charts/ChartProxy.swift +57 -0
  337. package/Sources/SwiftUI/Charts/Marks.swift +204 -0
  338. package/Sources/SwiftUI/Charts/Plottable.swift +99 -0
  339. package/Sources/SwiftUI/Charts/Scales.swift +326 -0
  340. package/Sources/SwiftUI/Localization/Localization.swift +498 -0
  341. package/Sources/SwiftUI/Localization/PluralRules.swift +127 -0
  342. package/Sources/SwiftUI/Runtime/Executor.swift +85 -0
  343. package/Sources/SwiftUI/Runtime/Exports.swift +101 -0
  344. package/Sources/SwiftUI/Runtime/ImageSource.swift +310 -0
  345. package/Sources/SwiftUI/Runtime/JSON.swift +143 -0
  346. package/Sources/SwiftUI/Runtime/JSONParser.swift +443 -0
  347. package/Sources/SwiftUI/Runtime/LazyRows.swift +99 -0
  348. package/Sources/SwiftUI/Runtime/Measurements.swift +140 -0
  349. package/Sources/SwiftUI/Runtime/Ops.swift +152 -0
  350. package/Sources/SwiftUI/Runtime/Reconciler.swift +219 -0
  351. package/Sources/SwiftUI/Runtime/Replay.swift +382 -0
  352. package/Sources/SwiftUI/Runtime/Runtime.swift +2146 -0
  353. package/Sources/SwiftUI/Runtime/Sameness.swift +152 -0
  354. package/Sources/SwiftUI/Runtime/ViewPath.swift +89 -0
  355. package/Sources/SwiftUI/Runtime/ViewTraits.swift +175 -0
  356. package/Sources/SwiftUI/Runtime/WebAuthHeadless.swift +49 -0
  357. package/Sources/Symbols/Symbols.swift +25 -0
  358. package/Sources/Translation/Translation.swift +423 -0
  359. package/Sources/UIKit/Activity.swift +213 -0
  360. package/Sources/UIKit/Alerts.swift +69 -0
  361. package/Sources/UIKit/AppDelegate.swift +222 -0
  362. package/Sources/UIKit/Appearance.swift +84 -0
  363. package/Sources/UIKit/ColorConversions.swift +70 -0
  364. package/Sources/UIKit/Controls.swift +225 -0
  365. package/Sources/UIKit/Device.swift +200 -0
  366. package/Sources/UIKit/Feedback.swift +65 -0
  367. package/Sources/UIKit/Font.swift +307 -0
  368. package/Sources/UIKit/Graphics.swift +204 -0
  369. package/Sources/UIKit/HostingController.swift +185 -0
  370. package/Sources/UIKit/Identity.swift +24 -0
  371. package/Sources/UIKit/Introspectable.swift +510 -0
  372. package/Sources/UIKit/Pasteboard.swift +363 -0
  373. package/Sources/UIKit/PhotoAlbum.swift +81 -0
  374. package/Sources/UIKit/RemoteNotifications.swift +15 -0
  375. package/Sources/UIKit/Representable.swift +288 -0
  376. package/Sources/UIKit/SafeArea.swift +12 -0
  377. package/Sources/UIKit/SceneDelegates.swift +132 -0
  378. package/Sources/UIKit/Scenes.swift +40 -0
  379. package/Sources/UIKit/ScrollView.swift +157 -0
  380. package/Sources/UIKit/ShortcutItems.swift +67 -0
  381. package/Sources/UIKit/SymbolConfiguration.swift +124 -0
  382. package/Sources/UIKit/TargetAction.swift +123 -0
  383. package/Sources/UIKit/TextPaste.swift +161 -0
  384. package/Sources/UIKit/TextView.swift +538 -0
  385. package/Sources/UIKit/UIKit.swift +292 -0
  386. package/Sources/UIKit/UIView.swift +855 -0
  387. package/Sources/UIKit/ViewTranslation.swift +311 -0
  388. package/Sources/UniformTypeIdentifiers/UTType.swift +196 -0
  389. package/Sources/UserNotifications/Content.swift +370 -0
  390. package/Sources/UserNotifications/NotificationCenter.swift +309 -0
  391. package/Sources/WeatherKit/WeatherKit.swift +228 -0
  392. package/Sources/WebKit/WebKit.swift +245 -0
  393. package/Sources/os/os.swift +376 -0
  394. package/Sources/zlib/zlib.swift +6 -0
  395. package/index.d.ts +2 -0
  396. package/index.mjs +16 -0
  397. package/manifest.d.mts +2 -0
  398. package/manifest.mjs +39 -0
  399. package/package.json +30 -4
  400. package/sync-sources.mjs +33 -0
@@ -0,0 +1,72 @@
1
+ // The structure of a GIF file, as Image I/O reports it: how many frames it
2
+ // has, each frame's delay and the number of times it loops. Reading it walks
3
+ // the file's blocks without decoding a pixel; the page decodes and composes
4
+ // a frame when it draws it (Web/src/gif.ts, docs/ops-protocol.md, "Animated
5
+ // GIFs").
6
+
7
+ /// A GIF's frames and loop count.
8
+ struct _GIFStructure: Equatable {
9
+ struct Frame: Equatable {
10
+ /// The graphic control extension's delay, in hundredths of a second.
11
+ var delay: Int
12
+ }
13
+
14
+ var frames: [Frame]
15
+ /// The Netscape application extension's count: 0 loops forever; nil when
16
+ /// the file has none (it plays once).
17
+ var loopCount: Int?
18
+ var hasGlobalColorMap: Bool
19
+
20
+ /// The structure of a GIF file; nil for anything else. A file cut short
21
+ /// has the frames that start before the cut.
22
+ static func parse(_ bytes: [UInt8]) -> _GIFStructure? {
23
+ guard bytes.count >= 13, bytes.starts(with: Array("GIF87a".utf8)) || bytes.starts(with: Array("GIF89a".utf8)) else { return nil }
24
+ let screen = bytes[10]
25
+ let hasGlobalColorMap = screen & 0x80 != 0
26
+ var index = 13 + (hasGlobalColorMap ? 3 << (Int(screen & 0x07) + 1) : 0)
27
+ var structure = _GIFStructure(frames: [], loopCount: nil, hasGlobalColorMap: hasGlobalColorMap)
28
+ var delay = 0
29
+
30
+ /// The index after the data sub-blocks starting at `start`; nil when the file ends first.
31
+ func skipSubBlocks(_ start: Int) -> Int? {
32
+ var at = start
33
+ while at < bytes.count {
34
+ let size = Int(bytes[at])
35
+ if size == 0 { return at + 1 }
36
+ at += 1 + size
37
+ }
38
+ return nil
39
+ }
40
+
41
+ while index < bytes.count {
42
+ switch bytes[index] {
43
+ case 0x21: // An extension: its label, then data sub-blocks.
44
+ guard index + 1 < bytes.count else { return structure }
45
+ let label = bytes[index + 1]
46
+ let body = index + 2
47
+ if label == 0xF9, body + 4 < bytes.count, bytes[body] >= 4 {
48
+ delay = Int(bytes[body + 2]) | Int(bytes[body + 3]) << 8
49
+ }
50
+ if label == 0xFF, body + 16 < bytes.count, bytes[body] == 11,
51
+ bytes[(body + 1)...(body + 11)].elementsEqual(Array("NETSCAPE2.0".utf8)) || bytes[(body + 1)...(body + 11)].elementsEqual(Array("ANIMEXTS1.0".utf8)),
52
+ bytes[body + 12] >= 3, bytes[body + 13] == 1 {
53
+ structure.loopCount = Int(bytes[body + 14]) | Int(bytes[body + 15]) << 8
54
+ }
55
+ guard let next = skipSubBlocks(body) else { return structure }
56
+ index = next
57
+ case 0x2C: // An image: its descriptor, a local color table, the LZW code size, the data.
58
+ guard index + 9 < bytes.count else { return structure }
59
+ let packed = bytes[index + 9]
60
+ var at = index + 10
61
+ if packed & 0x80 != 0 { at += 3 << (Int(packed & 0x07) + 1) }
62
+ guard at < bytes.count, let next = skipSubBlocks(at + 1) else { return structure }
63
+ structure.frames.append(Frame(delay: delay))
64
+ delay = 0
65
+ index = next
66
+ default: // The trailer (0x3B), or something that is not a block.
67
+ return structure
68
+ }
69
+ }
70
+ return structure
71
+ }
72
+ }
@@ -0,0 +1,248 @@
1
+ // `import ImageIO` for the browser: image sources over the shim's decoder.
2
+ // `CGImageSourceCreateWithData` reads the file's header (format, size)
3
+ // without decoding it; an image made from the source is a `CGImage` whose
4
+ // recipe is the file, which the page decodes when it draws it (with its
5
+ // EXIF rotation applied, so the properties report `.up`). An animated GIF
6
+ // has one image per frame, with its delay and the file's loop count in the
7
+ // properties (GIF.swift); the page composes the frame. Thumbnails are the
8
+ // image scaled to the requested size. Incremental sources produce no image
9
+ // until the data is complete. Destinations (encoding) are not available:
10
+ // creating one fails. See docs/ops-protocol.md, "Core Graphics and Image I/O"
11
+ // and "Animated GIFs".
12
+
13
+ @_exported import CoreGraphics
14
+ import struct Foundation.Data
15
+ import struct Foundation.URL
16
+ import class Foundation.NSMutableData
17
+ import SwiftUI
18
+
19
+ // Core Foundation's types, as Image I/O takes them (`data as CFData`,
20
+ // `options as CFDictionary`: plain Swift values here).
21
+ @_exported import CoreFoundationTypes
22
+
23
+ /// An image file, or the bytes of one so far.
24
+ public final class CGImageSource: @unchecked Sendable {
25
+ var data: Data {
26
+ didSet { read() }
27
+ }
28
+ var header: _ImageHeader?
29
+ /// A GIF's frames, read once the data is set.
30
+ var gif: _GIFStructure?
31
+ let isIncremental: Bool
32
+ var isFinal: Bool
33
+
34
+ init(data: Data, incremental: Bool, final: Bool) {
35
+ self.data = data
36
+ self.isIncremental = incremental
37
+ self.isFinal = final
38
+ read()
39
+ }
40
+
41
+ private func read() {
42
+ header = _ImageHeader.parse([UInt8](data.prefix(64 * 1024)))
43
+ gif = header?.mime == "image/gif" ? _GIFStructure.parse([UInt8](data)) : nil
44
+ }
45
+
46
+ /// The number of images: a GIF's frames (at least one once its header is
47
+ /// read), one for any other file.
48
+ var count: Int {
49
+ guard header != nil else { return 0 }
50
+ return max(1, gif?.frames.count ?? 1)
51
+ }
52
+
53
+ /// Whether the images are frames the page composes (an animated GIF).
54
+ var isAnimated: Bool { (gif?.frames.count ?? 0) > 1 }
55
+
56
+ /// The decoded file, ready to draw.
57
+ var source: _ImageSource? {
58
+ guard isFinal || !isIncremental else { return nil }
59
+ return _ImageSource(encoded: [UInt8](data))
60
+ }
61
+ }
62
+
63
+ public enum CGImageSourceStatus: Int32, Sendable {
64
+ case statusUnexpectedEOF = -5, statusInvalidData = -4, statusUnknownType = -3, statusReadingHeader = -2, statusIncomplete = -1, statusComplete = 0
65
+ }
66
+
67
+ public func CGImageSourceCreateWithData(_ data: CFData, _ options: CFDictionary?) -> CGImageSource? {
68
+ let source = CGImageSource(data: data, incremental: false, final: true)
69
+ return source.header == nil ? nil : source
70
+ }
71
+
72
+ /// A source over the file at a file URL (the app's own files); nil for
73
+ /// another scheme or a file that is not an image.
74
+ public func CGImageSourceCreateWithURL(_ url: Any, _ options: CFDictionary?) -> CGImageSource? {
75
+ guard let url = url as? URL, url.isFileURL, let data = try? Data(contentsOf: url) else { return nil }
76
+ return CGImageSourceCreateWithData(data, options)
77
+ }
78
+
79
+ public func CGImageSourceCreateIncremental(_ options: CFDictionary?) -> CGImageSource {
80
+ CGImageSource(data: Data(), incremental: true, final: false)
81
+ }
82
+
83
+ public func CGImageSourceUpdateData(_ source: CGImageSource, _ data: CFData, _ final: Bool) {
84
+ source.isFinal = final
85
+ source.data = data
86
+ }
87
+
88
+ public func CGImageSourceGetStatus(_ source: CGImageSource) -> CGImageSourceStatus {
89
+ guard source.header != nil else { return source.data.isEmpty ? .statusReadingHeader : .statusUnknownType }
90
+ return source.isFinal ? .statusComplete : .statusIncomplete
91
+ }
92
+
93
+ public func CGImageSourceGetStatusAtIndex(_ source: CGImageSource, _ index: Int) -> CGImageSourceStatus {
94
+ index >= 0 && index < source.count ? CGImageSourceGetStatus(source) : .statusInvalidData
95
+ }
96
+
97
+ /// The number of images: a GIF's frames, one for any other file.
98
+ public func CGImageSourceGetCount(_ source: CGImageSource) -> Int { source.count }
99
+
100
+ /// The file's uniform type identifier (`public.png`, `public.jpeg`, `com.compuserve.gif`, …).
101
+ public func CGImageSourceGetType(_ source: CGImageSource) -> CFString? {
102
+ _uniformType(ofMIME: source.header?.mime)
103
+ }
104
+
105
+ /// The file's size and, for a GIF, its loop count (0: forever; absent when
106
+ /// the file plays once), canvas size and whether it has a global color map.
107
+ public func CGImageSourceCopyProperties(_ source: CGImageSource, _ options: CFDictionary?) -> CFDictionary? {
108
+ guard let header = source.header else { return nil }
109
+ var properties: [String: Any] = [kCGImagePropertyFileSize: source.data.count]
110
+ if let gif = source.gif {
111
+ var dictionary: [String: Any] = [
112
+ kCGImagePropertyGIFHasGlobalColorMap: gif.hasGlobalColorMap,
113
+ kCGImagePropertyGIFCanvasPixelWidth: header.width,
114
+ kCGImagePropertyGIFCanvasPixelHeight: header.height,
115
+ ]
116
+ if let loopCount = gif.loopCount { dictionary[kCGImagePropertyGIFLoopCount] = loopCount }
117
+ properties[kCGImagePropertyGIFDictionary] = dictionary
118
+ }
119
+ return properties
120
+ }
121
+
122
+ /// The size and orientation (always up: the page applies EXIF rotation) of
123
+ /// image `index`; a GIF frame's delay in seconds, unclamped and as Image I/O
124
+ /// clamps it (a delay under 11 ms is shown for 100 ms, as browsers do).
125
+ public func CGImageSourceCopyPropertiesAtIndex(_ source: CGImageSource, _ index: Int, _ options: CFDictionary?) -> CFDictionary? {
126
+ guard index >= 0, index < source.count, let header = source.header else { return nil }
127
+ var properties: [String: Any] = [
128
+ kCGImagePropertyPixelWidth: header.width,
129
+ kCGImagePropertyPixelHeight: header.height,
130
+ kCGImagePropertyOrientation: UInt32(1),
131
+ ]
132
+ if header.mime == "image/jpeg" {
133
+ properties[kCGImagePropertyJFIFDictionary] = [kCGImagePropertyJFIFIsProgressive: _isProgressiveJPEG([UInt8](source.data.prefix(64 * 1024)))] as [String: Any]
134
+ }
135
+ if header.mime == "image/gif" {
136
+ var dictionary = [String: Any]()
137
+ if let frame = source.gif?.frames[safe: index] {
138
+ let unclamped = Double(frame.delay) / 100
139
+ dictionary[kCGImagePropertyGIFUnclampedDelayTime] = unclamped
140
+ dictionary[kCGImagePropertyGIFDelayTime] = unclamped < 0.011 ? 0.1 : unclamped
141
+ }
142
+ properties[kCGImagePropertyGIFDictionary] = dictionary
143
+ }
144
+ return properties
145
+ }
146
+
147
+ /// Image `index`: the file, or one frame of an animated GIF as the earlier
148
+ /// frames leave the canvas (the page composes it).
149
+ public func CGImageSourceCreateImageAtIndex(_ source: CGImageSource, _ index: Int, _ options: CFDictionary?) -> CGImage? {
150
+ guard index >= 0, index < source.count, let decoded = source.source else { return nil }
151
+ return CGImage(_recipe: _ImageRecipe(source: decoded, frame: source.isAnimated ? index : nil))
152
+ }
153
+
154
+ extension Array {
155
+ fileprivate subscript(safe index: Int) -> Element? { indices.contains(index) ? self[index] : nil }
156
+ }
157
+
158
+ /// The image scaled down so its longer side is at most
159
+ /// `kCGImageSourceThumbnailMaxPixelSize` (the whole image without it).
160
+ public func CGImageSourceCreateThumbnailAtIndex(_ source: CGImageSource, _ index: Int, _ options: CFDictionary?) -> CGImage? {
161
+ guard let image = CGImageSourceCreateImageAtIndex(source, index, options) else { return nil }
162
+ let maxSize = (options?[kCGImageSourceThumbnailMaxPixelSize] as? Int).map(Double.init)
163
+ ?? (options?[kCGImageSourceThumbnailMaxPixelSize] as? Double)
164
+ ?? (options?[kCGImageSourceThumbnailMaxPixelSize] as? CGFloat)
165
+ let longer = Double(max(image.width, image.height))
166
+ guard let maxSize, maxSize > 0, longer > maxSize else { return image }
167
+ let scale = maxSize / longer
168
+ let size = CGSize(width: (Double(image.width) * scale).rounded(), height: (Double(image.height) * scale).rounded())
169
+ guard let ctx = CGContext(data: nil, width: Int(size.width), height: Int(size.height), bitsPerComponent: 8, bytesPerRow: 0,
170
+ space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue) else { return image }
171
+ ctx.draw(image, in: CGRect(origin: .zero, size: size))
172
+ return ctx.makeImage()
173
+ }
174
+
175
+ /// Whether a JPEG's first frame header is progressive (SOF2).
176
+ func _isProgressiveJPEG(_ bytes: [UInt8]) -> Bool {
177
+ var i = 2
178
+ while i + 3 < bytes.count, bytes[i] == 0xFF {
179
+ let marker = bytes[i + 1]
180
+ if marker == 0xC2 { return true }
181
+ if marker >= 0xC0 && marker <= 0xCF && marker != 0xC4 && marker != 0xC8 && marker != 0xCC { return false }
182
+ let length = Int(bytes[i + 2]) << 8 | Int(bytes[i + 3])
183
+ i += 2 + length
184
+ }
185
+ return false
186
+ }
187
+
188
+ // MARK: - Destinations
189
+
190
+ /// Encoding is not available in the browser: no destination can be created.
191
+ public final class CGImageDestination: @unchecked Sendable {}
192
+
193
+ public func CGImageDestinationCreateWithData(_ data: Any, _ type: CFString, _ count: Int, _ options: CFDictionary?) -> CGImageDestination? { nil }
194
+ public func CGImageDestinationAddImage(_ destination: CGImageDestination, _ image: CGImage, _ properties: CFDictionary?) {}
195
+ public func CGImageDestinationFinalize(_ destination: CGImageDestination) -> Bool { false }
196
+ public func CGImageDestinationCopyTypeIdentifiers() -> [String] { [] }
197
+
198
+ // MARK: - Orientation
199
+
200
+ public enum CGImagePropertyOrientation: UInt32, Sendable {
201
+ case up = 1, upMirrored, down, downMirrored, leftMirrored, right, rightMirrored, left
202
+ }
203
+
204
+ // MARK: - Keys
205
+
206
+ public let kCGImageSourceTypeIdentifierHint: CFString = "kCGImageSourceTypeIdentifierHint"
207
+ public let kCGImageSourceShouldCache: CFString = "kCGImageSourceShouldCache"
208
+ public let kCGImageSourceShouldCacheImmediately: CFString = "kCGImageSourceShouldCacheImmediately"
209
+ public let kCGImageSourceShouldAllowFloat: CFString = "kCGImageSourceShouldAllowFloat"
210
+ public let kCGImageSourceCreateThumbnailFromImageIfAbsent: CFString = "kCGImageSourceCreateThumbnailFromImageIfAbsent"
211
+ public let kCGImageSourceCreateThumbnailFromImageAlways: CFString = "kCGImageSourceCreateThumbnailFromImageAlways"
212
+ public let kCGImageSourceThumbnailMaxPixelSize: CFString = "kCGImageSourceThumbnailMaxPixelSize"
213
+ public let kCGImageSourceCreateThumbnailWithTransform: CFString = "kCGImageSourceCreateThumbnailWithTransform"
214
+ public let kCGImageSourceSubsampleFactor: CFString = "kCGImageSourceSubsampleFactor"
215
+
216
+ public let kCGImagePropertyFileSize: CFString = "FileSize"
217
+ public let kCGImagePropertyPixelWidth: CFString = "PixelWidth"
218
+ public let kCGImagePropertyPixelHeight: CFString = "PixelHeight"
219
+ public let kCGImagePropertyOrientation: CFString = "Orientation"
220
+ public let kCGImagePropertyDPIWidth: CFString = "DPIWidth"
221
+ public let kCGImagePropertyDPIHeight: CFString = "DPIHeight"
222
+ public let kCGImagePropertyHasAlpha: CFString = "HasAlpha"
223
+ public let kCGImagePropertyColorModel: CFString = "ColorModel"
224
+ public let kCGImagePropertyJFIFDictionary: CFString = "{JFIF}"
225
+ public let kCGImagePropertyJFIFIsProgressive: CFString = "IsProgressive"
226
+ public let kCGImagePropertyGIFDictionary: CFString = "{GIF}"
227
+ public let kCGImagePropertyGIFDelayTime: CFString = "DelayTime"
228
+ public let kCGImagePropertyGIFUnclampedDelayTime: CFString = "UnclampedDelayTime"
229
+ public let kCGImagePropertyGIFLoopCount: CFString = "LoopCount"
230
+ public let kCGImagePropertyGIFHasGlobalColorMap: CFString = "HasGlobalColorMap"
231
+ public let kCGImagePropertyGIFCanvasPixelWidth: CFString = "CanvasPixelWidth"
232
+ public let kCGImagePropertyGIFCanvasPixelHeight: CFString = "CanvasPixelHeight"
233
+ public let kCGImagePropertyPNGDictionary: CFString = "{PNG}"
234
+ public let kCGImagePropertyAPNGDelayTime: CFString = "DelayTime"
235
+ public let kCGImagePropertyAPNGUnclampedDelayTime: CFString = "UnclampedDelayTime"
236
+ public let kCGImagePropertyAPNGLoopCount: CFString = "LoopCount"
237
+ public let kCGImagePropertyWebPDictionary: CFString = "{WebP}"
238
+ public let kCGImagePropertyWebPDelayTime: CFString = "DelayTime"
239
+ public let kCGImagePropertyWebPUnclampedDelayTime: CFString = "UnclampedDelayTime"
240
+ public let kCGImagePropertyWebPLoopCount: CFString = "LoopCount"
241
+ public let kCGImagePropertyHEICSDictionary: CFString = "{HEICS}"
242
+ public let kCGImagePropertyHEICSDelayTime: CFString = "DelayTime"
243
+ public let kCGImagePropertyHEICSUnclampedDelayTime: CFString = "UnclampedDelayTime"
244
+ public let kCGImagePropertyExifDictionary: CFString = "{Exif}"
245
+ public let kCGImagePropertyTIFFDictionary: CFString = "{TIFF}"
246
+ public let kCGImageDestinationLossyCompressionQuality: CFString = "kCGImageDestinationLossyCompressionQuality"
247
+ public let kCGImageDestinationEmbedThumbnail: CFString = "kCGImageDestinationEmbedThumbnail"
248
+ public let kCGImageDestinationImageMaxPixelSize: CFString = "kCGImageDestinationImageMaxPixelSize"
@@ -0,0 +1,28 @@
1
+ // `CGImage.utType` (iOS 15): the type of the file an image was decoded
2
+ // from. An image straight from a file (an image source's, a `UIImage(data:)`'s)
3
+ // has its file's type; one drawn or filtered since has none, as on iOS.
4
+
5
+ import SwiftUI
6
+
7
+ extension CGImage {
8
+ /// The uniform type identifier of the file the image is (`public.png`,
9
+ /// `public.jpeg`, …); nil once it has been drawn or filtered.
10
+ public var utType: CFString? {
11
+ guard _recipe.steps.isEmpty, let mime = _recipe.source?.mime else { return nil }
12
+ return _uniformType(ofMIME: mime)
13
+ }
14
+ }
15
+
16
+ /// The identifier of an image MIME type.
17
+ func _uniformType(ofMIME mime: String?) -> CFString? {
18
+ switch mime {
19
+ case "image/png": "public.png"
20
+ case "image/jpeg": "public.jpeg"
21
+ case "image/gif": "com.compuserve.gif"
22
+ case "image/webp": "org.webmproject.webp"
23
+ case "image/heic": "public.heic"
24
+ case "image/avif": "public.avif"
25
+ case "image/bmp": "com.microsoft.bmp"
26
+ default: nil
27
+ }
28
+ }
@@ -0,0 +1,249 @@
1
+ // `import LinkPresentation` for the browser: link previews.
2
+ //
3
+ // `LPLinkMetadata` (declared in UIKit, which needs it for the share sheet's
4
+ // item sources, and re-exported here) is a plain record of a link's title,
5
+ // URL and pictures; an app that fills it in itself (Ice Cubes' share sheet
6
+ // does) gets what it put there, and the share sheet uses its title.
7
+ //
8
+ // `LPMetadataProvider` fetches the page with the app's `URLSession` (the
9
+ // page's `fetch`) and reads its title and Open Graph tags. A browser only
10
+ // lets a page read another site's HTML when that site allows it (CORS), and
11
+ // most do not, so for most links the fetch fails and the provider reports
12
+ // `LPError.metadataFetchFailed`, as iOS does for a page it cannot load.
13
+ // `LPLinkView` keeps its metadata and draws nothing (docs/ops-protocol.md,
14
+ // "Sharing and media").
15
+
16
+ @_exported import class UIKit.LPLinkMetadata
17
+ import Foundation
18
+ import FoundationBridge
19
+ import SwiftUI
20
+ import UIKit
21
+
22
+ public let LPErrorDomain = "LPErrorDomain"
23
+
24
+ /// Why fetching metadata failed, with LinkPresentation's codes.
25
+ public struct LPError: Error, Hashable, Sendable, CustomNSError {
26
+ public enum Code: Int, Sendable {
27
+ case unknown = 1
28
+ case metadataFetchFailed = 2
29
+ case metadataFetchCancelled = 3
30
+ case metadataFetchTimedOut = 4
31
+ case metadataFetchNotAllowed = 5
32
+ }
33
+
34
+ public let code: Code
35
+ public init(_ code: Code) { self.code = code }
36
+
37
+ public static var unknown: Code { .unknown }
38
+ public static var metadataFetchFailed: Code { .metadataFetchFailed }
39
+ public static var metadataFetchCancelled: Code { .metadataFetchCancelled }
40
+ public static var metadataFetchTimedOut: Code { .metadataFetchTimedOut }
41
+ public static var metadataFetchNotAllowed: Code { .metadataFetchNotAllowed }
42
+
43
+ public static var errorDomain: String { LPErrorDomain }
44
+ public var errorCode: Int { code.rawValue }
45
+ public var errorUserInfo: [String: Any] { [:] }
46
+ }
47
+
48
+ /// `catch LPError.metadataFetchFailed`, as with an imported error.
49
+ public func ~= (code: LPError.Code, error: any Error) -> Bool {
50
+ (error as? LPError)?.code == code
51
+ }
52
+
53
+ /// Fetches a link's metadata: the page's title and Open Graph tags, where
54
+ /// the site lets the browser read it (see the top of the file). One fetch
55
+ /// per provider, as on iOS.
56
+ public final class LPMetadataProvider: @unchecked Sendable {
57
+ /// Whether to load the icon and image too. Kept: the metadata names
58
+ /// them by URL (`imageProvider` loads the picture on request).
59
+ public var shouldFetchSubresources = true
60
+ /// Seconds before the fetch gives up (`metadataFetchTimedOut`).
61
+ public var timeout: TimeInterval = 30
62
+
63
+ private var started = false
64
+ private var cancelled = false
65
+ private var task: Task<Void, Never>?
66
+
67
+ public init() {}
68
+
69
+ public func startFetchingMetadata(for url: URL, completionHandler: @escaping @Sendable (LPLinkMetadata?, (any Error)?) -> Void) {
70
+ guard !started else {
71
+ completionHandler(nil, LPError(.unknown))
72
+ return
73
+ }
74
+ started = true
75
+ task = Task { @MainActor [self] in
76
+ do {
77
+ let metadata = try await fetch(url)
78
+ completionHandler(cancelled ? nil : metadata, cancelled ? LPError(.metadataFetchCancelled) : nil)
79
+ } catch {
80
+ completionHandler(nil, error)
81
+ }
82
+ }
83
+ }
84
+
85
+ public func startFetchingMetadata(for url: URL) async throws -> LPLinkMetadata {
86
+ guard !started else { throw LPError(.unknown) }
87
+ started = true
88
+ let metadata = try await fetch(url)
89
+ if cancelled { throw LPError(.metadataFetchCancelled) }
90
+ return metadata
91
+ }
92
+
93
+ /// Stops a fetch: its handler hears `metadataFetchCancelled`.
94
+ public func cancel() {
95
+ cancelled = true
96
+ task?.cancel()
97
+ }
98
+
99
+ @MainActor
100
+ private func fetch(_ url: URL) async throws -> LPLinkMetadata {
101
+ guard let scheme = url.scheme?.lowercased(), scheme == "http" || scheme == "https" else { throw LPError(.metadataFetchNotAllowed) }
102
+ var request = FoundationBridge.URLRequest(url: url)
103
+ request.timeoutInterval = timeout
104
+ let data: Data
105
+ let response: FoundationBridge.URLResponse
106
+ do {
107
+ (data, response) = try await FoundationBridge.URLSession.shared.data(for: request)
108
+ } catch let error as FoundationBridge.URLError where error.code == .timedOut {
109
+ throw LPError(.metadataFetchTimedOut)
110
+ } catch {
111
+ throw LPError(.metadataFetchFailed)
112
+ }
113
+ if let http = response as? FoundationBridge.HTTPURLResponse, !(200..<300).contains(http.statusCode) { throw LPError(.metadataFetchFailed) }
114
+ return Self.metadata(html: String(decoding: data.prefix(512 * 1024), as: UTF8.self), originalURL: url, url: response.url ?? url)
115
+ }
116
+
117
+ /// The metadata in a page's HTML: `og:title` or `<title>`, `og:image`,
118
+ /// the icon `<link>`, `og:video`; relative URLs resolved against `url`.
119
+ static func metadata(html: String, originalURL: URL, url: URL) -> LPLinkMetadata {
120
+ let metadata = LPLinkMetadata()
121
+ metadata.originalURL = originalURL
122
+ metadata.url = url
123
+ let head = html.range(of: "</head>", options: .caseInsensitive).map { String(html[..<$0.lowerBound]) } ?? html
124
+ let tags = Self.tags(in: head)
125
+ func meta(_ names: String...) -> String? {
126
+ for name in names {
127
+ if let tag = tags.first(where: { $0.name == "meta" && ($0.attributes["property"] ?? $0.attributes["name"])?.lowercased() == name }),
128
+ let content = tag.attributes["content"], !content.isEmpty {
129
+ return content
130
+ }
131
+ }
132
+ return nil
133
+ }
134
+ metadata.title = meta("og:title", "twitter:title") ?? Self.title(in: head)
135
+ if let image = meta("og:image", "og:image:url", "twitter:image"), let imageURL = URL(string: image, relativeTo: url)?.absoluteURL {
136
+ metadata.imageProvider = Self.provider(for: imageURL)
137
+ }
138
+ if let icon = tags.first(where: { $0.name == "link" && ($0.attributes["rel"] ?? "").lowercased().split(separator: " ").contains("icon") }),
139
+ let href = icon.attributes["href"], let iconURL = URL(string: href, relativeTo: url)?.absoluteURL {
140
+ metadata.iconProvider = Self.provider(for: iconURL)
141
+ }
142
+ if let video = meta("og:video", "og:video:url"), let videoURL = URL(string: video, relativeTo: url)?.absoluteURL {
143
+ metadata.remoteVideoURL = videoURL
144
+ }
145
+ return metadata
146
+ }
147
+
148
+ /// A provider that downloads the picture at `url` when loaded.
149
+ private static func provider(for url: URL) -> NSItemProvider {
150
+ let provider = NSItemProvider()
151
+ let type = UTType(filenameExtension: url.pathExtension, conformingTo: .image) ?? .image
152
+ provider.registerDataRepresentation(for: type.conforms(to: .image) ? type : .image) { completion in
153
+ Task { @MainActor in
154
+ do { completion(try await FoundationBridge.URLSession.shared.data(from: url).0, nil) } catch { completion(nil, error) }
155
+ }
156
+ return nil
157
+ }
158
+ return provider
159
+ }
160
+
161
+ private static func title(in html: String) -> String? {
162
+ guard let open = html.range(of: "<title", options: .caseInsensitive),
163
+ let close = html.range(of: ">", range: open.upperBound..<html.endIndex),
164
+ let end = html.range(of: "</title>", options: .caseInsensitive, range: close.upperBound..<html.endIndex)
165
+ else { return nil }
166
+ let text = decodeEntities(String(html[close.upperBound..<end.lowerBound])).trimmingCharacters(in: .whitespacesAndNewlines)
167
+ return text.isEmpty ? nil : text
168
+ }
169
+
170
+ struct Tag {
171
+ let name: String
172
+ let attributes: [String: String]
173
+ }
174
+
175
+ /// The `<meta>` and `<link>` tags, with their attributes (names lower-cased, values decoded).
176
+ static func tags(in html: String) -> [Tag] {
177
+ var tags: [Tag] = []
178
+ var rest = html[...]
179
+ while let open = rest.range(of: "<") {
180
+ rest = rest[open.upperBound...]
181
+ guard let close = rest.range(of: ">") else { break }
182
+ let body = rest[..<close.lowerBound]
183
+ rest = rest[close.upperBound...]
184
+ let name = body.prefix { $0.isLetter }.lowercased()
185
+ guard name == "meta" || name == "link" else { continue }
186
+ tags.append(Tag(name: name, attributes: attributes(String(body.dropFirst(name.count)))))
187
+ }
188
+ return tags
189
+ }
190
+
191
+ private static func attributes(_ text: String) -> [String: String] {
192
+ var result: [String: String] = [:]
193
+ var scanner = text[...]
194
+ while true {
195
+ scanner = scanner.drop { $0.isWhitespace || $0 == "/" }
196
+ let key = scanner.prefix { !$0.isWhitespace && $0 != "=" && $0 != "/" }
197
+ guard !key.isEmpty else { break }
198
+ scanner = scanner.dropFirst(key.count).drop { $0.isWhitespace }
199
+ var value = ""
200
+ if scanner.first == "=" {
201
+ scanner = scanner.dropFirst().drop { $0.isWhitespace }
202
+ if let quote = scanner.first, quote == "\"" || quote == "'" {
203
+ let inner = scanner.dropFirst().prefix { $0 != quote }
204
+ value = String(inner)
205
+ scanner = scanner.dropFirst(inner.count + 2)
206
+ } else {
207
+ let bare = scanner.prefix { !$0.isWhitespace }
208
+ value = String(bare)
209
+ scanner = scanner.dropFirst(bare.count)
210
+ }
211
+ }
212
+ result[key.lowercased()] = decodeEntities(value)
213
+ }
214
+ return result
215
+ }
216
+
217
+ private static func decodeEntities(_ text: String) -> String {
218
+ guard text.contains("&") else { return text }
219
+ var result = text
220
+ for (entity, character) in [("&amp;", "&"), ("&lt;", "<"), ("&gt;", ">"), ("&quot;", "\""), ("&#39;", "'"), ("&apos;", "'"), ("&#x27;", "'")] {
221
+ result = result.replacingOccurrences(of: entity, with: character)
222
+ }
223
+ return result
224
+ }
225
+ }
226
+
227
+ /// A rich link preview. Kept with its metadata; it draws nothing (no
228
+ /// representable translates it).
229
+ @MainActor
230
+ open class LPLinkView: UIView {
231
+ open var metadata: LPLinkMetadata
232
+
233
+ public init(metadata: LPLinkMetadata) {
234
+ self.metadata = metadata
235
+ super.init(frame: .zero)
236
+ }
237
+
238
+ public convenience init(url: URL) {
239
+ let metadata = LPLinkMetadata()
240
+ metadata.originalURL = url
241
+ metadata.url = url
242
+ self.init(metadata: metadata)
243
+ }
244
+
245
+ public required init?(coder: NSCoder) {
246
+ metadata = LPLinkMetadata()
247
+ super.init(coder: coder)
248
+ }
249
+ }