From a7acb0506f4e46f53160270139b23fc3c5bf43cb Mon Sep 17 00:00:00 2001 From: quoid Date: Wed, 3 Mar 2021 20:03:07 -0500 Subject: [PATCH 01/40] font size adjustment to better reflect reality --- src/Components/Shared/Tag.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Components/Shared/Tag.svelte b/src/Components/Shared/Tag.svelte index a10310b4..89870cf4 100644 --- a/src/Components/Shared/Tag.svelte +++ b/src/Components/Shared/Tag.svelte @@ -8,7 +8,7 @@ border: 1px solid var(--color-red); border-radius: var(--border-radius); color: var(--color-red); - font-size: 0.313rem; + font-size: 0.563rem; font-weight: 500; letter-spacing: 0.022rem; line-height: 0.75rem; From 688176b6dff8e35422f23c6337f194564812dceb Mon Sep 17 00:00:00 2001 From: quoid Date: Sat, 6 Mar 2021 14:17:29 -0500 Subject: [PATCH 02/40] update version and build numbers --- extension/Userscripts.xcodeproj/project.pbxproj | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/extension/Userscripts.xcodeproj/project.pbxproj b/extension/Userscripts.xcodeproj/project.pbxproj index f5649f03..2d66ee70 100644 --- a/extension/Userscripts.xcodeproj/project.pbxproj +++ b/extension/Userscripts.xcodeproj/project.pbxproj @@ -409,7 +409,7 @@ CODE_SIGN_ENTITLEMENTS = "Userscripts Extension/Userscripts Extension.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 24; + CURRENT_PROJECT_VERSION = 25; DEVELOPMENT_TEAM = J74Q8V8V8N; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "Userscripts Extension/Info.plist"; @@ -418,7 +418,7 @@ "@executable_path/../Frameworks", "@executable_path/../../../../Frameworks", ); - MARKETING_VERSION = 3.0.2; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.userscripts.macos.Userscripts-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -432,7 +432,7 @@ CODE_SIGN_ENTITLEMENTS = "Userscripts Extension/Userscripts Extension.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 24; + CURRENT_PROJECT_VERSION = 25; DEVELOPMENT_TEAM = J74Q8V8V8N; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = "Userscripts Extension/Info.plist"; @@ -441,7 +441,7 @@ "@executable_path/../Frameworks", "@executable_path/../../../../Frameworks", ); - MARKETING_VERSION = 3.0.2; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = "com.userscripts.macos.Userscripts-Extension"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -458,7 +458,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 24; + CURRENT_PROJECT_VERSION = 25; DEVELOPMENT_TEAM = J74Q8V8V8N; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Userscripts/Info.plist; @@ -466,7 +466,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 3.0.2; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = com.userscripts.macos; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; @@ -482,7 +482,7 @@ CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 24; + CURRENT_PROJECT_VERSION = 25; DEVELOPMENT_TEAM = J74Q8V8V8N; ENABLE_HARDENED_RUNTIME = YES; INFOPLIST_FILE = Userscripts/Info.plist; @@ -490,7 +490,7 @@ "$(inherited)", "@executable_path/../Frameworks", ); - MARKETING_VERSION = 3.0.2; + MARKETING_VERSION = 3.1.0; PRODUCT_BUNDLE_IDENTIFIER = com.userscripts.macos; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 5.0; From 5d9945eef0a4a10951e108b5a90a338346c3873d Mon Sep 17 00:00:00 2001 From: quoid Date: Sat, 6 Mar 2021 14:46:45 -0500 Subject: [PATCH 03/40] update version --- src/dev.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dev.js b/src/dev.js index a97ffe99..fb83b9dc 100644 --- a/src/dev.js +++ b/src/dev.js @@ -15,7 +15,7 @@ const defaultSettings = { showInvisibles: "true", sortOrder: "lastModifiedDesc", tabSize: "4", - version: "3.0.2" + version: "3.1.0" }; // example file contents From 9c10bd611655cb83826ff37c7625938c869c04a2 Mon Sep 17 00:00:00 2001 From: quoid Date: Sat, 6 Mar 2021 14:47:20 -0500 Subject: [PATCH 04/40] rebuild extension html --- extension/Userscripts Extension/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/Userscripts Extension/index.html b/extension/Userscripts Extension/index.html index 7e5163ce..2b9ecd61 100644 --- a/extension/Userscripts Extension/index.html +++ b/extension/Userscripts Extension/index.html @@ -1 +1 @@ -Userscripts Safari
\ No newline at end of file +Userscripts Safari
\ No newline at end of file From 9fd0a565bc3ca23d24495af3b39e9ef9d202cd02 Mon Sep 17 00:00:00 2001 From: quoid Date: Sat, 6 Mar 2021 14:55:37 -0500 Subject: [PATCH 05/40] show active script badge in toolbar, related #103 --- .../Userscripts Extension/Functions.swift | 239 +++++++++--------- .../SafariExtensionHandler.swift | 17 +- 2 files changed, 131 insertions(+), 125 deletions(-) diff --git a/extension/Userscripts Extension/Functions.swift b/extension/Userscripts Extension/Functions.swift index cde9f8a0..d28158dd 100644 --- a/extension/Userscripts Extension/Functions.swift +++ b/extension/Userscripts Extension/Functions.swift @@ -999,58 +999,28 @@ func getRequiredCode(_ filename: String, _ resources: [String], _ fileType: Stri } // injection -func getCode(_ url: String, _ isTop: Bool) -> [String: [String: [String: Any]]]? { - var allFiles = [String: [String: [String: Any]]]() // will be returned - - // there has to be a better way to do this - - // dictionary to hold the indiv. css files that will be loaded - // ["file.css": ["code": "/* code here */", "weight": "1"]] - var cssFiles = [String:[String:String]]() - - // dictionary to hold the indiv. js files that will be loaded - // ["scope": ["timing": ["file.js": ["code": "// code", "weight": "1"]]]] - var jsFiles = [String: [String: [String: [String: String]]]]() - jsFiles["auto"] = ["document-start": [:], "document-end": [:], "document-idle": [:]] - jsFiles["content"] = ["document-start": [:], "document-end": [:], "document-idle": [:]] - jsFiles["page"] = ["document-start": [:], "document-end": [:], "document-idle": [:]] - - var auto_docStart = [String: [String: String]]() - var auto_docEnd = [String: [String: String]]() - var auto_docIdle = [String: [String: String]]() - var content_docStart = [String: [String: String]]() - var content_docEnd = [String: [String: String]]() - var content_docIdle = [String: [String: String]]() - var page_docStart = [String: [String: String]]() - var page_docEnd = [String: [String: String]]() - var page_docIdle = [String: [String: String]]() - - // domains where loading is excluded for file - var excludedFilenames:[String] = [] - - // when code is loaded from a file, it's filename will be populated in the below array, to avoid duplication - var matchedFilenames:[String] = [] - +func getMatchedFiles(_ url: String) -> [String]? { // get the manifest data guard let manifestKeys = getManifestKeys() else { - err("could not read manifest when attempting to get code for injection") + err("could not read manifest when attempting to get page script count") return nil } - - // url matches a pattern in blacklist, return empty dict - for pattern in manifestKeys.blacklist { - if patternMatch(url, pattern) { - return allFiles - } - } - - // AT THIS POINT IT IS KNOWN THAT THE URL IS NOT IN THE BLACKLIST, PROCEED - + // domains where loading is excluded for file + var excludedFilenames:[String] = [] + // when code is loaded from a file, it's filename will be populated in the below array, to avoid duplication + var matchedFilenames:[String] = [] // all exclude patterns from manifest let excludePatterns = manifestKeys.exclude.keys - // all match patterns from manifest let matchPatterns = manifestKeys.match.keys + + // url matches a pattern in blacklist + // essentially all scripts are disabled, there are 0 active scripts for url + for pattern in manifestKeys.blacklist { + if patternMatch(url, pattern) { + return matchedFilenames + } + } // add disabled script filenames to excludePatterns excludedFilenames.append(contentsOf: manifestKeys.disabled) @@ -1071,7 +1041,7 @@ func getCode(_ url: String, _ isTop: Bool) -> [String: [String: [String: Any]]]? } } - // loop through all match patterns from manifest to see if they match against the current page url (func arg) + // loop through all match patterns from manifest to see if they match against the current page url for pattern in matchPatterns { if patternMatch(url, pattern) { // the filenames listed for the pattern that match page url @@ -1079,88 +1049,109 @@ func getCode(_ url: String, _ isTop: Bool) -> [String: [String: [String: Any]]]? err("error parsing manifestKets.match when attempting to get code for injected script") continue } - // loop through matched filenames and get corresponding code from file + // loop through matched filenames and populate matchedFilenames array for filename in filenames { - // don't load if filename is in excludes or filename already exists in matchedFilenames array (to avoid duplication) + // don't push to array if filename is in excludes or filename already exists in matchedFilenames array (to avoid duplication) if !excludedFilenames.contains(filename) && !matchedFilenames.contains(filename) { - // if guards fail, log error continue to next file - guard - // NOTE: getFileContents returns parsed script metadata - let saveLocation = getSaveLocation(), - let contents = getFileContentsParsed(saveLocation.appendingPathComponent(filename)), - var code = contents["code"] as? String, - let type = filename.split(separator: ".").last - else { - err("could not get file contents for \(filename)") - continue - } - - // can force unwrap b/c getFileContentsParsed ensures metadata exists - let metadata = contents["metadata"] as! [String: [String]] - - // if metadata has noframes option and the url is not the top window, don't load - if (metadata["noframes"] != nil && !isTop) { - continue - } - - // normalize weight - var weight = metadata["weight"]?[0] ?? "1" - weight = normalizeWeight(weight) - - // attempt to get require resource from disk - // if required resource is inaccessible, silently fail and continue - if let required = metadata["require"] { - for require in required { - let sanitizedName = santize(require) ?? "" - let requiredFileURL = getRequireLocation().appendingPathComponent(filename).appendingPathComponent(sanitizedName) - if let requiredContent = try? String(contentsOf: requiredFileURL, encoding: .utf8) { - code = "\(requiredContent)\n\(code)" - } else { - err("could not get required resource from disk \(requiredFileURL)") - } - } - } - - if type == "css" { - cssFiles[filename] = ["code": code, "weight": weight] - } else if type == "js" { - var injectInto = metadata["inject-into"]?[0] ?? "page" - var runAt = metadata["run-at"]?[0] ?? "document-end" - - // ensure values are acceptable - let injectVals = ["auto", "content", "page"] - let runAtVals = ["document-start", "document-end", "document-idle"] - if !injectVals.contains(injectInto) { - injectInto = "page" - } - if !runAtVals.contains(runAt) { - runAt = "document-end" - } - - let data = ["code": code, "weight": weight] - // add file data to appropiate dict - if injectInto == "auto" && runAt == "document-start" { - auto_docStart[filename] = data - } else if injectInto == "auto" && runAt == "document-end" { - auto_docEnd[filename] = data - } else if injectInto == "auto" && runAt == "document-idle" { - auto_docIdle[filename] = data - } else if injectInto == "content" && runAt == "document-start" { - content_docStart[filename] = data - } else if injectInto == "content" && runAt == "document-end" { - content_docEnd[filename] = data - } else if injectInto == "content" && runAt == "document-idle" { - content_docIdle[filename] = data - } else if injectInto == "page" && runAt == "document-start" { - page_docStart[filename] = data - } else if injectInto == "page" && runAt == "document-end" { - page_docEnd[filename] = data - } else if injectInto == "page" && runAt == "document-idle" { - page_docIdle[filename] = data - } - } + matchedFilenames.append(filename) } - matchedFilenames.append(filename) + } + + } + } + return matchedFilenames +} + +func getCode(_ filenames: [String], _ isTop: Bool)-> [String: [String: [String: Any]]]? { + var allFiles = [String: [String: [String: Any]]]() + var cssFiles = [String:[String:String]]() + var jsFiles = [String: [String: [String: [String: String]]]]() + jsFiles["auto"] = ["document-start": [:], "document-end": [:], "document-idle": [:]] + jsFiles["content"] = ["document-start": [:], "document-end": [:], "document-idle": [:]] + jsFiles["page"] = ["document-start": [:], "document-end": [:], "document-idle": [:]] + var auto_docStart = [String: [String: String]]() + var auto_docEnd = [String: [String: String]]() + var auto_docIdle = [String: [String: String]]() + var content_docStart = [String: [String: String]]() + var content_docEnd = [String: [String: String]]() + var content_docIdle = [String: [String: String]]() + var page_docStart = [String: [String: String]]() + var page_docEnd = [String: [String: String]]() + var page_docIdle = [String: [String: String]]() + + for filename in filenames { + guard + let saveLocation = getSaveLocation(), + let contents = getFileContentsParsed(saveLocation.appendingPathComponent(filename)), + var code = contents["code"] as? String, + let type = filename.split(separator: ".").last + else { + // if guard fails, log error continue to next file + err("could not get file contents for \(filename)") + continue + } + // can force unwrap b/c getFileContentsParsed ensures metadata exists + let metadata = contents["metadata"] as! [String: [String]] + + // if metadata has noframes option and the url is not the top window, don't load + if (metadata["noframes"] != nil && !isTop) { + continue + } + + // normalize weight + var weight = metadata["weight"]?[0] ?? "1" + weight = normalizeWeight(weight) + + // attempt to get require resource from disk + // if required resource is inaccessible, log error and continue + if let required = metadata["require"] { + for require in required { + let sanitizedName = santize(require) ?? "" + let requiredFileURL = getRequireLocation().appendingPathComponent(filename).appendingPathComponent(sanitizedName) + if let requiredContent = try? String(contentsOf: requiredFileURL, encoding: .utf8) { + code = "\(requiredContent)\n\(code)" + } else { + err("could not get required resource from disk \(requiredFileURL)") + } + } + } + + if type == "css" { + cssFiles[filename] = ["code": code, "weight": weight] + } else if type == "js" { + var injectInto = metadata["inject-into"]?[0] ?? "page" + var runAt = metadata["run-at"]?[0] ?? "document-end" + + let injectVals = ["auto", "content", "page"] + let runAtVals = ["document-start", "document-end", "document-idle"] + // if inject/runAt values are not valid, use default + if !injectVals.contains(injectInto) { + injectInto = "page" + } + if !runAtVals.contains(runAt) { + runAt = "document-end" + } + + let data = ["code": code, "weight": weight] + // add file data to appropiate dict + if injectInto == "auto" && runAt == "document-start" { + auto_docStart[filename] = data + } else if injectInto == "auto" && runAt == "document-end" { + auto_docEnd[filename] = data + } else if injectInto == "auto" && runAt == "document-idle" { + auto_docIdle[filename] = data + } else if injectInto == "content" && runAt == "document-start" { + content_docStart[filename] = data + } else if injectInto == "content" && runAt == "document-end" { + content_docEnd[filename] = data + } else if injectInto == "content" && runAt == "document-idle" { + content_docIdle[filename] = data + } else if injectInto == "page" && runAt == "document-start" { + page_docStart[filename] = data + } else if injectInto == "page" && runAt == "document-end" { + page_docEnd[filename] = data + } else if injectInto == "page" && runAt == "document-idle" { + page_docIdle[filename] = data } } } diff --git a/extension/Userscripts Extension/SafariExtensionHandler.swift b/extension/Userscripts Extension/SafariExtensionHandler.swift index d824baa9..96877765 100644 --- a/extension/Userscripts Extension/SafariExtensionHandler.swift +++ b/extension/Userscripts Extension/SafariExtensionHandler.swift @@ -96,7 +96,8 @@ class SafariExtensionHandler: SFSafariExtensionHandler { let url = data["url"] as? String, let isTop = data["top"] as? Bool, let id = data["id"] as? String, - let code = getCode(url, isTop) + let matched = getMatchedFiles(url), + let code = getCode(matched, isTop) { responseData = ["code": code, "id": id] } else { @@ -121,6 +122,20 @@ class SafariExtensionHandler: SFSafariExtensionHandler { override func validateToolbarItem(in window: SFSafariWindow, validationHandler: @escaping ((Bool, String) -> Void)) { validationHandler(true, "") + window.getActiveTab { tab in + tab?.getActivePage { page in + page?.getPropertiesWithCompletionHandler { props in + if let url = props?.url { + guard let matched = getMatchedFiles(url.absoluteString) else { return } + if matched.count > 0 { + window.getToolbarItem { toolbaritem in + toolbaritem?.setBadgeText(String(matched.count)) + } + } + } + } + } + } } } From fdf14d02b041420971a82da3785b3d4144e9f90c Mon Sep 17 00:00:00 2001 From: quoid Date: Sat, 6 Mar 2021 15:18:34 -0500 Subject: [PATCH 06/40] add setting to toggle toolbar count, related #103 --- extension/Userscripts Extension/Functions.swift | 1 + .../Userscripts Extension/SafariExtensionHandler.swift | 8 ++++++-- src/Components/Settings.svelte | 7 +++++++ src/dev.js | 1 + 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/extension/Userscripts Extension/Functions.swift b/extension/Userscripts Extension/Functions.swift index d28158dd..a554c361 100644 --- a/extension/Userscripts Extension/Functions.swift +++ b/extension/Userscripts Extension/Functions.swift @@ -259,6 +259,7 @@ let defaultSettings = [ "lint": "false", "log": "false", "sortOrder": "lastModifiedDesc", + "showCount": "false", "showInvisibles": "true", "tabSize": "4" ] diff --git a/extension/Userscripts Extension/SafariExtensionHandler.swift b/extension/Userscripts Extension/SafariExtensionHandler.swift index 96877765..fe4da6e9 100644 --- a/extension/Userscripts Extension/SafariExtensionHandler.swift +++ b/extension/Userscripts Extension/SafariExtensionHandler.swift @@ -126,8 +126,12 @@ class SafariExtensionHandler: SFSafariExtensionHandler { tab?.getActivePage { page in page?.getPropertiesWithCompletionHandler { props in if let url = props?.url { - guard let matched = getMatchedFiles(url.absoluteString) else { return } - if matched.count > 0 { + guard + let matched = getMatchedFiles(url.absoluteString), + let manifestKeys = getManifestKeys(), + let showCount = manifestKeys.settings["showCount"] + else { return } + if matched.count > 0 && showCount == "true" { window.getToolbarItem { toolbaritem in toolbaritem?.setBadgeText(String(matched.count)) } diff --git a/src/Components/Settings.svelte b/src/Components/Settings.svelte index 6d4bef99..ca831cb1 100644 --- a/src/Components/Settings.svelte +++ b/src/Components/Settings.svelte @@ -225,6 +225,13 @@ on:click={() => update("log", !$settings.log)} /> +