From 503ccd5d37531dc1ae21e46ef008c8c9ce2992da Mon Sep 17 00:00:00 2001 From: Leonardo Cardoso Date: Thu, 23 Sep 2021 18:46:01 +0200 Subject: [PATCH 1/5] Bump version to 3.5.0 --- CHANGELOG.md | 8 ++++++++ Example/SwiftLinkPreviewExample/Info.plist | 2 +- README.md | 8 ++++---- Sources/Info-macOS.plist | 2 +- Sources/Info-tvOS.plist | 2 +- Sources/Info-watchOS.plist | 2 +- Sources/Info.plist | 2 +- SwiftLinkPreview.podspec | 4 ++-- SwiftLinkPreviewTests/Info-macOS.plist | 2 +- SwiftLinkPreviewTests/Info-tvOS.plist | 2 +- SwiftLinkPreviewTests/Info.plist | 2 +- 11 files changed, 22 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1319ad..c93b285 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Change Log #### 3.x Releases +- `3.5.x` Releases - [3.5.0](#350) - `3.4.x` Releases - [3.4.0](#340) - `3.3.x` Releases - [3.3.0](#330) - `3.2.x` Releases - [3.2.0](#320) @@ -22,6 +23,13 @@ --- +## [3.5.0](https://github.com/LeonardoCardoso/Swift-Link-Preview/releases/tag/3.5.0) + +#### Changed +- Update README.md [#150](https://github.com/LeonardoCardoso/SwiftLinkPreview/issues/150) + - Changed by [benlmyers](https://github.com/benlmyers) + + ## [3.4.0](https://github.com/LeonardoCardoso/Swift-Link-Preview/releases/tag/3.4.0) #### Added diff --git a/Example/SwiftLinkPreviewExample/Info.plist b/Example/SwiftLinkPreviewExample/Info.plist index f89431e..209ba21 100644 --- a/Example/SwiftLinkPreviewExample/Info.plist +++ b/Example/SwiftLinkPreviewExample/Info.plist @@ -19,7 +19,7 @@ CFBundleSignature ???? CFBundleVersion - 3.4.0 + 3.5.0 LSRequiresIPhoneOS NSAppTransportSecurity diff --git a/README.md b/README.md index 527553d..e5f1435 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ > It makes a preview from an URL, grabbing all the information such as title, relevant texts and images. [![Platform](https://img.shields.io/badge/platform-iOS%20|%20macOS%20|%20watchOS%20|%20tvOS-orange.svg)](https://github.com/LeonardoCardoso/SwiftLinkPreview#requirements-and-details) -[![CocoaPods](https://img.shields.io/badge/pod-v3.4.0-red.svg)](https://github.com/LeonardoCardoso/SwiftLinkPreview#cocoapods) +[![CocoaPods](https://img.shields.io/badge/pod-v3.5.0-red.svg)](https://github.com/LeonardoCardoso/SwiftLinkPreview#cocoapods) [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg)](https://github.com/LeonardoCardoso/SwiftLinkPreview#carthage) [![Swift Package Manager](https://img.shields.io/badge/SPM-compatible-orange.svg)](https://github.com/LeonardoCardoso/SwiftLinkPreview#swift-package-manager) [![Build Status](https://travis-ci.org/LeonardoCardoso/SwiftLinkPreview.svg?branch=master)](https://travis-ci.org/LeonardoCardoso/SwiftLinkPreview) @@ -59,7 +59,7 @@ To use **SwiftLinkPreview** as a pod package just add the following in your **Po target 'Your Target Name' do use_frameworks! // ... - pod 'SwiftLinkPreview', '~> 3.4.0' + pod 'SwiftLinkPreview', '~> 3.5.0' // ... end ``` @@ -70,7 +70,7 @@ To use **SwiftLinkPreview** as a Carthage module package just add the following ```ruby // ... - github "LeonardoCardoso/SwiftLinkPreview" ~> 3.4.0 + github "LeonardoCardoso/SwiftLinkPreview" ~> 3.5.0 // ... ``` @@ -85,7 +85,7 @@ let package = Package( name: "Your Target Name", dependencies: [ // ... - .Package(url: "https://github.com/LeonardoCardoso/SwiftLinkPreview.git", "3.4.0") + .Package(url: "https://github.com/LeonardoCardoso/SwiftLinkPreview.git", "3.5.0") // ... ] ) diff --git a/Sources/Info-macOS.plist b/Sources/Info-macOS.plist index 648e64f..311f45e 100644 --- a/Sources/Info-macOS.plist +++ b/Sources/Info-macOS.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.4.0 + 3.5.0 CFBundleSignature ???? CFBundleVersion diff --git a/Sources/Info-tvOS.plist b/Sources/Info-tvOS.plist index a8f98d8..2bf762f 100644 --- a/Sources/Info-tvOS.plist +++ b/Sources/Info-tvOS.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.4.0 + 3.5.0 CFBundleSignature ???? CFBundleVersion diff --git a/Sources/Info-watchOS.plist b/Sources/Info-watchOS.plist index a8f98d8..2bf762f 100644 --- a/Sources/Info-watchOS.plist +++ b/Sources/Info-watchOS.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.4.0 + 3.5.0 CFBundleSignature ???? CFBundleVersion diff --git a/Sources/Info.plist b/Sources/Info.plist index a8f98d8..2bf762f 100644 --- a/Sources/Info.plist +++ b/Sources/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.4.0 + 3.5.0 CFBundleSignature ???? CFBundleVersion diff --git a/SwiftLinkPreview.podspec b/SwiftLinkPreview.podspec index 1323514..2a9855d 100755 --- a/SwiftLinkPreview.podspec +++ b/SwiftLinkPreview.podspec @@ -7,12 +7,12 @@ Pod::Spec.new do |s| s.name = "SwiftLinkPreview" s.summary = "It makes a preview from an url, grabbing all the information such as title, relevant texts and images." s.requires_arc = true - s.version = "3.4.0" + s.version = "3.5.0" s.license = { :type => "MIT", :file => "LICENSE" } s.author = { "Leonardo Cardoso" => "contact@leocardz.com" } s.homepage = "https://github.com/LeonardoCardoso/SwiftLinkPreview" s.source = { :git => "https://github.com/LeonardoCardoso/SwiftLinkPreview.git", :tag => s.version } s.source_files = "Sources/**/*.swift" - s.swift_version = '4.2' + s.swift_version = '5' end diff --git a/SwiftLinkPreviewTests/Info-macOS.plist b/SwiftLinkPreviewTests/Info-macOS.plist index 6521e7a..589caa7 100644 --- a/SwiftLinkPreviewTests/Info-macOS.plist +++ b/SwiftLinkPreviewTests/Info-macOS.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 3.4.0 + 3.5.0 CFBundleSignature ???? CFBundleVersion diff --git a/SwiftLinkPreviewTests/Info-tvOS.plist b/SwiftLinkPreviewTests/Info-tvOS.plist index 6521e7a..589caa7 100644 --- a/SwiftLinkPreviewTests/Info-tvOS.plist +++ b/SwiftLinkPreviewTests/Info-tvOS.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 3.4.0 + 3.5.0 CFBundleSignature ???? CFBundleVersion diff --git a/SwiftLinkPreviewTests/Info.plist b/SwiftLinkPreviewTests/Info.plist index 6521e7a..589caa7 100644 --- a/SwiftLinkPreviewTests/Info.plist +++ b/SwiftLinkPreviewTests/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType BNDL CFBundleShortVersionString - 3.4.0 + 3.5.0 CFBundleSignature ???? CFBundleVersion From 53b1116b38fea183e90b0e660a80431e7596106a Mon Sep 17 00:00:00 2001 From: Leonardo Cardoso Date: Thu, 23 Sep 2021 19:14:13 +0200 Subject: [PATCH 2/5] Update example --- Example/SwiftLinkPreviewExample.xcodeproj/project.pbxproj | 7 +++---- .../xcschemes/SwiftLinkPreviewExample.xcscheme | 2 +- SwiftLinkPreview.xcodeproj/project.pbxproj | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Example/SwiftLinkPreviewExample.xcodeproj/project.pbxproj b/Example/SwiftLinkPreviewExample.xcodeproj/project.pbxproj index 9a0b079..2c28ba3 100644 --- a/Example/SwiftLinkPreviewExample.xcodeproj/project.pbxproj +++ b/Example/SwiftLinkPreviewExample.xcodeproj/project.pbxproj @@ -164,10 +164,9 @@ }; buildConfigurationList = 98846C721D09AA1B00846726 /* Build configuration list for PBXProject "SwiftLinkPreviewExample" */; compatibilityVersion = "Xcode 8.0"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - English, en, Base, ); @@ -334,7 +333,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -386,7 +385,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; diff --git a/Example/SwiftLinkPreviewExample.xcodeproj/xcshareddata/xcschemes/SwiftLinkPreviewExample.xcscheme b/Example/SwiftLinkPreviewExample.xcodeproj/xcshareddata/xcschemes/SwiftLinkPreviewExample.xcscheme index 6dcaab6..cfc9d11 100644 --- a/Example/SwiftLinkPreviewExample.xcodeproj/xcshareddata/xcschemes/SwiftLinkPreviewExample.xcscheme +++ b/Example/SwiftLinkPreviewExample.xcodeproj/xcshareddata/xcschemes/SwiftLinkPreviewExample.xcscheme @@ -1,6 +1,6 @@ Date: Sat, 31 Jul 2021 13:33:48 +0700 Subject: [PATCH 3/5] Merge pull request #1 from kinhvodoi92/kinhvodoi92-fixRegexLimit update Regex.swift. Upgrade regex limit length --- CHANGELOG.md | 4 +++- Sources/Regex.swift | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c93b285..9e6efc6 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,8 +26,10 @@ ## [3.5.0](https://github.com/LeonardoCardoso/Swift-Link-Preview/releases/tag/3.5.0) #### Changed -- Update README.md [#150](https://github.com/LeonardoCardoso/SwiftLinkPreview/issues/150) +- Updated README.md [#150](https://github.com/LeonardoCardoso/SwiftLinkPreview/issues/150) - Changed by [benlmyers](https://github.com/benlmyers) +- Updated regex limit [#148](https://github.com/LeonardoCardoso/SwiftLinkPreview/issues/148) + - Changed by [kinhvodoi92](https://github.com/kinhvodoi92) ## [3.4.0](https://github.com/LeonardoCardoso/Swift-Link-Preview/releases/tag/3.4.0) diff --git a/Sources/Regex.swift b/Sources/Regex.swift index c4e08dc..843db2b 100644 --- a/Sources/Regex.swift +++ b/Sources/Regex.swift @@ -71,7 +71,7 @@ class Regex { var matches: [NSTextCheckingResult] = [] - let limit = 300000 + let limit = 1000000 if string.count > limit { string.split(by: limit).forEach { From 5ade1dec7bd5b86ef98e50e19945f37df200d42c Mon Sep 17 00:00:00 2001 From: Leonardo Cardoso Date: Thu, 23 Sep 2021 19:30:03 +0200 Subject: [PATCH 4/5] Annotate cancel an @objc method #135 --- CHANGELOG.md | 2 ++ Sources/SwiftLinkPreview.swift | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e6efc6..f0699d7 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ - Changed by [benlmyers](https://github.com/benlmyers) - Updated regex limit [#148](https://github.com/LeonardoCardoso/SwiftLinkPreview/issues/148) - Changed by [kinhvodoi92](https://github.com/kinhvodoi92) +- Annotated `Cancelable.cancel()` as `@objc` to make it compatibale with Objective-C [#135](https://github.com/LeonardoCardoso/SwiftLinkPreview/issues/135) + - Changed by [LeonardoCardoso](https://github.com/LeonardoCardoso) ## [3.4.0](https://github.com/LeonardoCardoso/Swift-Link-Preview/releases/tag/3.4.0) diff --git a/Sources/SwiftLinkPreview.swift b/Sources/SwiftLinkPreview.swift index 58b4d86..86f2f36 100644 --- a/Sources/SwiftLinkPreview.swift +++ b/Sources/SwiftLinkPreview.swift @@ -23,7 +23,7 @@ public enum SwiftLinkResponseKey: String { open class Cancellable: NSObject { public private(set) var isCancelled: Bool = false - open func cancel() { + @objc open func cancel() { isCancelled = true } } From 415b3a9b731315b3d43e10cdc8b706d98f966a6e Mon Sep 17 00:00:00 2001 From: Leonardo Cardoso Date: Thu, 23 Sep 2021 20:28:49 +0200 Subject: [PATCH 5/5] Capture baseURL --- CHANGELOG.md | 8 ++- .../Controllers/ViewController.swift | 4 +- README.md | 21 +++---- Sources/Regex.swift | 7 ++- Sources/Response.swift | 3 +- Sources/ResponseExtension.swift | 6 ++ Sources/SwiftLinkPreview.swift | 55 ++++++++++++++++--- SwiftLinkPreview.xcodeproj/project.pbxproj | 44 ++++++++++----- SwiftLinkPreviewTests/BaseURLTests.swift | 55 +++++++++++++++++++ SwiftLinkPreviewTests/Constants.swift | 1 + SwiftLinkPreviewTests/head-meta-base.html | 10 ++++ SwiftLinkPreviewTests/head-meta-facebook.html | 2 +- SwiftLinkPreviewTests/head-meta-meta.html | 2 +- 13 files changed, 176 insertions(+), 42 deletions(-) create mode 100644 SwiftLinkPreviewTests/BaseURLTests.swift create mode 100644 SwiftLinkPreviewTests/head-meta-base.html diff --git a/CHANGELOG.md b/CHANGELOG.md index f0699d7..d6e4e3e 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,13 +25,17 @@ ## [3.5.0](https://github.com/LeonardoCardoso/Swift-Link-Preview/releases/tag/3.5.0) +#### Added +- Annotated `Cancelable.cancel()` as `@objc` to make it compatibale with Objective-C [#135](https://github.com/LeonardoCardoso/SwiftLinkPreview/issues/135) +- Added removal of duplicates from the images array [#45](https://github.com/LeonardoCardoso/SwiftLinkPreview/issues/45) +- Added capture of base URL [#45](https://github.com/LeonardoCardoso/SwiftLinkPreview/issues/45) + - Changed by [LeonardoCardoso](https://github.com/LeonardoCardoso) + #### Changed - Updated README.md [#150](https://github.com/LeonardoCardoso/SwiftLinkPreview/issues/150) - Changed by [benlmyers](https://github.com/benlmyers) - Updated regex limit [#148](https://github.com/LeonardoCardoso/SwiftLinkPreview/issues/148) - Changed by [kinhvodoi92](https://github.com/kinhvodoi92) -- Annotated `Cancelable.cancel()` as `@objc` to make it compatibale with Objective-C [#135](https://github.com/LeonardoCardoso/SwiftLinkPreview/issues/135) - - Changed by [LeonardoCardoso](https://github.com/LeonardoCardoso) ## [3.4.0](https://github.com/LeonardoCardoso/Swift-Link-Preview/releases/tag/3.4.0) diff --git a/Example/SwiftLinkPreviewExample/Controllers/ViewController.swift b/Example/SwiftLinkPreviewExample/Controllers/ViewController.swift index 3bb2d28..9339003 100644 --- a/Example/SwiftLinkPreviewExample/Controllers/ViewController.swift +++ b/Example/SwiftLinkPreviewExample/Controllers/ViewController.swift @@ -38,8 +38,9 @@ class ViewController: UIViewController { "www.youtube.com", "www.google.com", "facebook.com", - + "https://github.com/LeonardoCardoso/SwiftLinkPreview", + "https://www.jbhifi.com.au/products/playstation-4-biomutant", "https://leocardz.com/swift-link-preview-5a9860c7756f", "NASA! 🖖🏽 https://www.nasa.gov/", @@ -268,6 +269,7 @@ class ViewController: UIViewController { print("video: ", result.video ?? "no video") print("icon: ", result.icon ?? "no icon") print("description: ", result.description ?? "no description") + print("baseURL: ", result.baseURL ?? "no baseURL") } guard textField?.text?.isEmpty == false else { diff --git a/README.md b/README.md index e5f1435..c2e23ca 100644 --- a/README.md +++ b/README.md @@ -121,16 +121,17 @@ let preview = slp.preview("Text containing URL", ```swift Response { - let url: URL // URL - let finalUrl: URL // unshortened URL - let canonicalUrl: String // canonical URL - let title: String // title - let description: String // page description or relevant text - let images: [String] // array of URLs of the images - let image: String // main image - let icon: String // favicon - let video: String // video - let price: String // price + let baseURL: String? // base + let url: URL? // URL + let finalUrl: URL? // unshortened URL + let canonicalUrl: String? // canonical URL + let title: String? // title + let description: String? // page description or relevant text + let images: [String]? // array of URLs of the images + let image: String? // main image + let icon: String? // favicon + let video: String? // video + let price: String? // price } ``` diff --git a/Sources/Regex.swift b/Sources/Regex.swift index 843db2b..3e44d8b 100644 --- a/Sources/Regex.swift +++ b/Sources/Regex.swift @@ -17,8 +17,9 @@ class Regex { static let imageTagPattern = "" static let secondaryImageTagPattern = "og:image\"(.+?)content=\"([^\"](.+?))\"(.+?)[/]?>" static let titlePattern = "(.*?)" - static let metatagPattern = "" - static let metatagContentPattern = "content=(\"(.*?)\")|('(.*?)')" + static let metaTagPattern = "" + static let baseTagPattern = "" + static let metaTagContentPattern = "content=(\"(.*?)\")|('(.*?)')" static let cannonicalUrlPattern = "([^\\+&#@%\\?=~_\\|!:,;]+)" static let rawTagPattern = "<[^>]+>" static let inlineStylePattern = "(.*?)" @@ -71,7 +72,7 @@ class Regex { var matches: [NSTextCheckingResult] = [] - let limit = 1000000 + let limit = 300000 if string.count > limit { string.split(by: limit).forEach { diff --git a/Sources/Response.swift b/Sources/Response.swift index d20f657..c3ef506 100644 --- a/Sources/Response.swift +++ b/Sources/Response.swift @@ -9,7 +9,8 @@ import Foundation public struct Response { - + + public internal(set) var baseURL: String? public internal(set) var url: URL? public internal(set) var finalUrl: URL? public internal(set) var canonicalUrl: String? diff --git a/Sources/ResponseExtension.swift b/Sources/ResponseExtension.swift index d3dd9b3..169748b 100644 --- a/Sources/ResponseExtension.swift +++ b/Sources/ResponseExtension.swift @@ -12,6 +12,7 @@ internal extension Response { var dictionary: [String: Any] { var responseData:[String: Any] = [:] + responseData["baseURL"] = baseURL responseData["url"] = url responseData["finalUrl"] = finalUrl responseData["canonicalUrl"] = canonicalUrl @@ -35,11 +36,14 @@ internal extension Response { case images case icon case video + case baseURL case price } mutating func set(_ value: Any, for key: Key) { switch key { + case Key.baseURL: + if let value = value as? String { self.baseURL = value } case Key.url: if let value = value as? URL { self.url = value } case Key.finalUrl: @@ -65,6 +69,8 @@ internal extension Response { func value(for key: Key) -> Any? { switch key { + case Key.baseURL: + return self.baseURL case Key.url: return self.url case Key.finalUrl: diff --git a/Sources/SwiftLinkPreview.swift b/Sources/SwiftLinkPreview.swift index 86f2f36..308f5ee 100644 --- a/Sources/SwiftLinkPreview.swift +++ b/Sources/SwiftLinkPreview.swift @@ -127,15 +127,17 @@ open class SwiftLinkPreview: NSObject { result.url = url result.finalUrl = self.extractInURLRedirectionIfNeeded(unshortened) result.canonicalUrl = self.extractCanonicalURL(unshortened) + result.baseURL = result.baseURL ?? (result.canonicalUrl?.starts(with: "http") == false ? "https://\(result.canonicalUrl!)" : result.canonicalUrl) self.extractInfo(response: result, cancellable: cancellable, completion: { result.title = $0.title result.description = $0.description - result.image = $0.image - result.images = $0.images - result.icon = $0.icon - result.video = $0.video + + result.image = self.formatImageURL($0.image, base: $0.baseURL) + result.images = self.formatImageURLs($0.images, base: $0.baseURL) + result.icon = self.formatImageURL($0.icon, base: $0.baseURL) + result.video = self.formatImageURL($0.video, base: $0.baseURL) result.price = $0.price self.cache.slp_setCachedResponse(url: unshortened.absoluteString, response: result) @@ -154,6 +156,28 @@ open class SwiftLinkPreview: NSObject { return cancellable } + private func formatImageURL(_ url: String?, base: String?) -> String? { + guard var url = url else { return nil } + + if !url.starts(with: "http"), let base = base { + url = "\(base)\(url)" + } + + return url + } + + func formatImageURLs(_ array: [String]?, base: String?) -> [String]? { + guard var array = array else { return nil } + + for i in 0 ..< array.count { + if let formatted = formatImageURL(array[0], base: base) { + array[i] = formatted + } + } + + return Array(Set(array)) + } + /* Extract url redirection inside the GET query. Like https://www.dji.com/404?url=http%3A%2F%2Fwww.dji.com%2Fmatrice600-pro%2Finfo#specs -> http://www.dji.com/de/matrice600-pro/info#specs @@ -287,9 +311,9 @@ extension SwiftLinkPreview { CFStringConvertIANACharSetNameToEncoding( $0 as CFString ) ) ) } ?? .utf8 if let html = String( data: data, encoding: encoding ) { - for meta in Regex.pregMatchAll( html, regex: Regex.metatagPattern, index: 1 ) { + for meta in Regex.pregMatchAll( html, regex: Regex.metaTagPattern, index: 1 ) { if (meta.contains( "http-equiv=\"refresh\"" ) || meta.contains( "http-equiv='refresh'" )), - let value = Regex.pregMatchFirst( meta, regex: Regex.metatagContentPattern, index: 2 )?.decoded.extendedTrim, + let value = Regex.pregMatchFirst( meta, regex: Regex.metaTagContentPattern, index: 2 )?.decoded.extendedTrim, let redirectString = value.split( separator: ";" ) .first( where: { $0.lowercased().starts( with: "url=" ) } )? .split( separator: "=", maxSplits: 1 ).last, @@ -444,6 +468,8 @@ extension SwiftLinkPreview { result = self.crawlMetaTags(sanitizedHtmlCode, result: result) + result = self.crawlMetaBase(sanitizedHtmlCode, result: result) + var otherResponse = self.crawlTitle(sanitizedHtmlCode, result: result) otherResponse = self.crawlDescription(otherResponse.htmlCode, result: otherResponse.result) @@ -534,10 +560,10 @@ extension SwiftLinkPreview { Response.Key.title.rawValue, Response.Key.description.rawValue, Response.Key.image.rawValue, - Response.Key.video.rawValue, + Response.Key.video.rawValue ] - let metatags = Regex.pregMatchAll(htmlCode, regex: Regex.metatagPattern, index: 1) + let metatags = Regex.pregMatchAll(htmlCode, regex: Regex.metaTagPattern, index: 1) for metatag in metatags { for tag in possibleTags { @@ -552,7 +578,7 @@ extension SwiftLinkPreview { if let key = Response.Key(rawValue: tag), result.value(for: key) == nil { - if let value = Regex.pregMatchFirst(metatag, regex: Regex.metatagContentPattern, index: 2) { + if let value = Regex.pregMatchFirst(metatag, regex: Regex.metaTagContentPattern, index: 2) { let value = value.decoded.extendedTrim if tag == "image" { let value = addImagePrefixIfNeeded(value, result: result) @@ -572,6 +598,17 @@ extension SwiftLinkPreview { return result } + internal func crawlMetaBase(_ htmlCode: String, result: Response) -> Response { + + var result = result + + if let base = Regex.pregMatchAll(htmlCode, regex: Regex.baseTagPattern, index: 2).first { + result.set(base, for: .baseURL) + } + + return result + } + // Crawl for title if needed internal func crawlTitle(_ htmlCode: String, result: Response) -> (htmlCode: String, result: Response) { var result = result diff --git a/SwiftLinkPreview.xcodeproj/project.pbxproj b/SwiftLinkPreview.xcodeproj/project.pbxproj index 403e874..3ee57ac 100644 --- a/SwiftLinkPreview.xcodeproj/project.pbxproj +++ b/SwiftLinkPreview.xcodeproj/project.pbxproj @@ -8,6 +8,12 @@ /* Begin PBXBuildFile section */ 1F8164ED26287866000F2905 /* VideoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8164EC26287866000F2905 /* VideoTests.swift */; }; + 27BCC85826FCF22E00886BDA /* BaseURLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27BCC85726FCF22E00886BDA /* BaseURLTests.swift */; }; + 27BCC85D26FCF3BF00886BDA /* BaseURLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27BCC85726FCF22E00886BDA /* BaseURLTests.swift */; }; + 27BCC85E26FCF3C000886BDA /* BaseURLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 27BCC85726FCF22E00886BDA /* BaseURLTests.swift */; }; + 27BCC86026FCF4C000886BDA /* head-meta-base.html in Resources */ = {isa = PBXBuildFile; fileRef = 27BCC85F26FCF4C000886BDA /* head-meta-base.html */; }; + 27BCC86126FCF4C000886BDA /* head-meta-base.html in Resources */ = {isa = PBXBuildFile; fileRef = 27BCC85F26FCF4C000886BDA /* head-meta-base.html */; }; + 27BCC86226FCF4C000886BDA /* head-meta-base.html in Resources */ = {isa = PBXBuildFile; fileRef = 27BCC85F26FCF4C000886BDA /* head-meta-base.html */; }; 68074FFA1F23B6C900649DE6 /* head-meta-icon.html in Resources */ = {isa = PBXBuildFile; fileRef = 68074FF91F23B6C900649DE6 /* head-meta-icon.html */; }; 68074FFB1F23BB1100649DE6 /* head-meta-icon.html in Resources */ = {isa = PBXBuildFile; fileRef = 68074FF91F23B6C900649DE6 /* head-meta-icon.html */; }; 68074FFC1F23BB1400649DE6 /* head-meta-icon.html in Resources */ = {isa = PBXBuildFile; fileRef = 68074FF91F23B6C900649DE6 /* head-meta-icon.html */; }; @@ -150,6 +156,8 @@ /* Begin PBXFileReference section */ 1F8164EC26287866000F2905 /* VideoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoTests.swift; sourceTree = ""; }; + 27BCC85726FCF22E00886BDA /* BaseURLTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseURLTests.swift; sourceTree = ""; }; + 27BCC85F26FCF4C000886BDA /* head-meta-base.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "head-meta-base.html"; sourceTree = ""; }; 68074FF91F23B6C900649DE6 /* head-meta-icon.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "head-meta-icon.html"; sourceTree = ""; }; 686E58DE1F22416D000C2A33 /* IconTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IconTests.swift; sourceTree = ""; }; 7A552DE121A460910019E8B1 /* Response.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = ""; }; @@ -257,17 +265,18 @@ 985DCEB01D2BFD2700B40D76 /* Files */ = { isa = PBXGroup; children = ( - 98B5ED421D3E5F5C00AEBD54 /* head-meta-itemprop.html */, - 986D5BE61D33E0FD0025555F /* head-title.html */, - 985DCEBB1D2BFFAF00B40D76 /* body-text-span.html */, - 985DCEBC1D2BFFAF00B40D76 /* body-text-p.html */, - 985DCEBD1D2BFFAF00B40D76 /* body-text-div.html */, - 985DCEB71D2BFE4100B40D76 /* body-image-single.html */, 985DCEB81D2BFE4100B40D76 /* body-image-gallery.html */, - 985DCEB11D2BFD3400B40D76 /* head-meta-twitter.html */, - 985DCEB21D2BFD3400B40D76 /* head-meta-meta.html */, + 985DCEB71D2BFE4100B40D76 /* body-image-single.html */, + 985DCEBD1D2BFFAF00B40D76 /* body-text-div.html */, + 985DCEBC1D2BFFAF00B40D76 /* body-text-p.html */, + 985DCEBB1D2BFFAF00B40D76 /* body-text-span.html */, + 27BCC85F26FCF4C000886BDA /* head-meta-base.html */, 985DCEB31D2BFD3400B40D76 /* head-meta-facebook.html */, 68074FF91F23B6C900649DE6 /* head-meta-icon.html */, + 98B5ED421D3E5F5C00AEBD54 /* head-meta-itemprop.html */, + 985DCEB21D2BFD3400B40D76 /* head-meta-meta.html */, + 985DCEB11D2BFD3400B40D76 /* head-meta-twitter.html */, + 986D5BE61D33E0FD0025555F /* head-title.html */, ); name = Files; sourceTree = ""; @@ -358,18 +367,19 @@ 98DC53391D1D73DB001134E3 /* SwiftLinkPreviewTests */ = { isa = PBXGroup; children = ( - 98B5ED491D3E7DC600AEBD54 /* HugeTests.swift */, + 27BCC85726FCF22E00886BDA /* BaseURLTests.swift */, 985DCEC81D2C029700B40D76 /* BodyTests.swift */, + 988B48D61D2C3C2E0040A4AD /* Constants */, + 985DCEB01D2BFD2700B40D76 /* Files */, + 98B5ED491D3E7DC600AEBD54 /* HugeTests.swift */, + 686E58DE1F22416D000C2A33 /* IconTests.swift */, 985DCEC61D2C026000B40D76 /* ImageTests.swift */, - 1F8164EC26287866000F2905 /* VideoTests.swift */, + 98E7C3121D3B23F5009E5F6D /* Info */, 985DCEC41D2C022E00B40D76 /* MetaTests.swift */, 982812911D3A9293000D3ABB /* RegexTests.swift */, 986D5BE41D33DFE50025555F /* TitleTests.swift */, - 686E58DE1F22416D000C2A33 /* IconTests.swift */, - 988B48D61D2C3C2E0040A4AD /* Constants */, - 985DCEB01D2BFD2700B40D76 /* Files */, - 98E7C3121D3B23F5009E5F6D /* Info */, 988B48D11D2C39790040A4AD /* Utils */, + 1F8164EC26287866000F2905 /* VideoTests.swift */, ); path = SwiftLinkPreviewTests; sourceTree = ""; @@ -641,6 +651,7 @@ 985DCEBF1D2BFFAF00B40D76 /* body-text-span.html in Resources */, 985DCEC01D2BFFAF00B40D76 /* body-text-p.html in Resources */, 985DCEC11D2BFFAF00B40D76 /* body-text-div.html in Resources */, + 27BCC86026FCF4C000886BDA /* head-meta-base.html in Resources */, 985DCEB91D2BFE4100B40D76 /* body-image-single.html in Resources */, 985DCEB61D2BFD3400B40D76 /* head-meta-facebook.html in Resources */, 986D5BE71D33E0FD0025555F /* head-title.html in Resources */, @@ -666,6 +677,7 @@ 98E7C32F1D3B24DA009E5F6D /* body-image-single.html in Resources */, 98B5ED461D3E62A200AEBD54 /* head-meta-itemprop.html in Resources */, 98E7C3301D3B24DA009E5F6D /* body-image-gallery.html in Resources */, + 27BCC86226FCF4C000886BDA /* head-meta-base.html in Resources */, 98E7C3311D3B24DA009E5F6D /* head-meta-twitter.html in Resources */, 98E7C3321D3B24DA009E5F6D /* head-meta-meta.html in Resources */, 98E7C3331D3B24DA009E5F6D /* head-meta-facebook.html in Resources */, @@ -691,6 +703,7 @@ 98F76D1D1D3AF87100E9B10E /* body-image-single.html in Resources */, 98B5ED441D3E62A000AEBD54 /* head-meta-itemprop.html in Resources */, 98F76D1E1D3AF87100E9B10E /* body-image-gallery.html in Resources */, + 27BCC86126FCF4C000886BDA /* head-meta-base.html in Resources */, 98F76D1F1D3AF87100E9B10E /* head-meta-twitter.html in Resources */, 98F76D201D3AF87100E9B10E /* head-meta-meta.html in Resources */, 98F76D211D3AF87100E9B10E /* head-meta-facebook.html in Resources */, @@ -740,6 +753,7 @@ 986D5BE51D33DFE60025555F /* TitleTests.swift in Sources */, 985DCEC71D2C026000B40D76 /* ImageTests.swift in Sources */, 988B48D81D2C3C3D0040A4AD /* Constants.swift in Sources */, + 27BCC85826FCF22E00886BDA /* BaseURLTests.swift in Sources */, 9272A10D1E2EF0E600F9F17E /* Regex.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -777,6 +791,7 @@ 98E7C3281D3B24C6009E5F6D /* File.swift in Sources */, 98E7C3291D3B24C6009E5F6D /* IntExtension.swift in Sources */, 9272A10F1E2EF0E800F9F17E /* Regex.swift in Sources */, + 27BCC85E26FCF3C000886BDA /* BaseURLTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -813,6 +828,7 @@ 98F76D121D3AF78600E9B10E /* File.swift in Sources */, 98F76D131D3AF78600E9B10E /* IntExtension.swift in Sources */, 9272A10E1E2EF0E700F9F17E /* Regex.swift in Sources */, + 27BCC85D26FCF3BF00886BDA /* BaseURLTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/SwiftLinkPreviewTests/BaseURLTests.swift b/SwiftLinkPreviewTests/BaseURLTests.swift new file mode 100644 index 0000000..33ee379 --- /dev/null +++ b/SwiftLinkPreviewTests/BaseURLTests.swift @@ -0,0 +1,55 @@ +// +// BaseURLTests.swift +// SwiftLinkPreviewTests +// +// Created by Leonardo Cardoso on 23.09.21. +// Copyright © 2021 leocardz.com. All rights reserved. +// + +import XCTest +@testable import SwiftLinkPreview + +// This class tests head meta info +class BaseURLTests: XCTestCase { + + // MARK: - Vars + var baseTemplate = "" + let slp = SwiftLinkPreview() + + // MARK: - SetUps + // Those setup functions get that template, and fulfil determinated areas with rand texts, images and tags + override func setUp() { + super.setUp() + + self.baseTemplate = File.toString(Constants.headMetaBase) + + } + + // MARK: - Base + func setUpBaseAndRun() { + + var baseTemplate = self.baseTemplate + baseTemplate = baseTemplate.replace(Constants.headRandom, with: String.randomTag()) + baseTemplate = baseTemplate.replace(Constants.bodyRandom, with: String.randomTag()).extendedTrim + + let result = self.slp.crawlMetaBase(baseTemplate, result: Response()) + + XCTAssertEqual(result.baseURL, "https://host/resource/index/") + } + + func testBase() { + + for _ in 0 ..< 100 { + + self.setUpBaseAndRun() + + } + + } + + func testResultBase() { + XCTAssertEqual(slp.formatImageURLs(["assets/test.png"], base: "https://host/resource/index/")?.first, + "https://host/resource/index/assets/test.png") + } + +} diff --git a/SwiftLinkPreviewTests/Constants.swift b/SwiftLinkPreviewTests/Constants.swift index db15838..e04a9fb 100644 --- a/SwiftLinkPreviewTests/Constants.swift +++ b/SwiftLinkPreviewTests/Constants.swift @@ -20,6 +20,7 @@ struct Constants { static let bodyIcon = "head-meta-icon" static let headMetaTwitter = "head-meta-twitter" static let headMetaMeta = "head-meta-meta" + static let headMetaBase = "head-meta-base" static let headMetaItemprop = "head-meta-itemprop" static let headMetaFacebook = "head-meta-facebook" static let headTitle = "head-title" diff --git a/SwiftLinkPreviewTests/head-meta-base.html b/SwiftLinkPreviewTests/head-meta-base.html new file mode 100644 index 0000000..7f66076 --- /dev/null +++ b/SwiftLinkPreviewTests/head-meta-base.html @@ -0,0 +1,10 @@ + + + [:head-random] + + + + [:body-random] + + + diff --git a/SwiftLinkPreviewTests/head-meta-facebook.html b/SwiftLinkPreviewTests/head-meta-facebook.html index 7d1b9d9..79e01b1 100644 --- a/SwiftLinkPreviewTests/head-meta-facebook.html +++ b/SwiftLinkPreviewTests/head-meta-facebook.html @@ -10,4 +10,4 @@ [:body-random] - \ No newline at end of file + diff --git a/SwiftLinkPreviewTests/head-meta-meta.html b/SwiftLinkPreviewTests/head-meta-meta.html index a6575a3..cb09599 100644 --- a/SwiftLinkPreviewTests/head-meta-meta.html +++ b/SwiftLinkPreviewTests/head-meta-meta.html @@ -10,4 +10,4 @@ [:body-random] - \ No newline at end of file +