diff --git a/.github/codeql/codeql-config.yml b/.github/codeql/codeql-config.yml new file mode 100644 index 0000000..5c3bcdf --- /dev/null +++ b/.github/codeql/codeql-config.yml @@ -0,0 +1,5 @@ +name: "Flean Swift CodeQL" + +paths: + - ios + - mos diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5990d9c..6867e71 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,7 +5,7 @@ version: 2 updates: - - package-ecosystem: "" # See documentation for possible values - directory: "/" # Location of package manifests + - package-ecosystem: "github-actions" + directory: "/" schedule: interval: "weekly" diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..1869d08 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,77 @@ +name: CodeQL (Swift) + +on: + push: + branches: + - main + paths: + - '**.swift' + - 'ios/**' + - 'mos/**' + - '.github/workflows/codeql.yml' + - '.github/codeql/**' + pull_request: + branches: + - main + paths: + - '**.swift' + - 'ios/**' + - 'mos/**' + - '.github/workflows/codeql.yml' + - '.github/codeql/**' + schedule: + - cron: '0 8 * * 1' + workflow_dispatch: + +permissions: + contents: read + security-events: write + +jobs: + analyze: + name: Analyze + runs-on: macos-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: swift + config-file: ./.github/codeql/codeql-config.yml + + # The projects do not contain shared schemes, so build with explicit targets. + - name: Build iOS app for analysis + run: | + cd ios + xcodebuild build \ + -project Flean.xcodeproj \ + -target Flean \ + -configuration Debug \ + -sdk iphonesimulator \ + -skipPackagePluginValidation \ + CODE_SIGNING_ALLOWED=NO \ + CODE_SIGNING_REQUIRED=NO \ + CODE_SIGN_IDENTITY="" + + - name: Build macOS app for analysis + run: | + cd mos + xcodebuild build \ + -project Flean.xcodeproj \ + -target Flean \ + -configuration Debug \ + -sdk macosx \ + -skipPackagePluginValidation \ + CODE_SIGNING_ALLOWED=NO \ + CODE_SIGNING_REQUIRED=NO \ + CODE_SIGN_IDENTITY="" + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: '/language:swift' diff --git a/ios/Flean.xcodeproj/project.pbxproj b/ios/Flean.xcodeproj/project.pbxproj index 3c96a79..ad03046 100644 --- a/ios/Flean.xcodeproj/project.pbxproj +++ b/ios/Flean.xcodeproj/project.pbxproj @@ -381,7 +381,7 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_ASSET_PATHS = extention; DEVELOPMENT_TEAM = PWL627GZ4Y; GENERATE_INFOPLIST_FILE = YES; @@ -394,7 +394,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -417,7 +417,7 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_ASSET_PATHS = extention; DEVELOPMENT_TEAM = PWL627GZ4Y; GENERATE_INFOPLIST_FILE = YES; @@ -430,7 +430,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -577,7 +577,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = Flean/Flean.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = PWL627GZ4Y; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_CFBundleDisplayName = Flean; @@ -588,7 +588,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -613,7 +613,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = Flean/Flean.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = PWL627GZ4Y; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_CFBundleDisplayName = Flean; @@ -624,7 +624,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -647,11 +647,11 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = PWL627GZ4Y; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; PRODUCT_BUNDLE_IDENTIFIER = slf.FleanTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; @@ -665,11 +665,11 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = PWL627GZ4Y; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; PRODUCT_BUNDLE_IDENTIFIER = slf.FleanTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; @@ -682,10 +682,10 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = PWL627GZ4Y; GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; PRODUCT_BUNDLE_IDENTIFIER = slf.FleanUITests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; @@ -698,10 +698,10 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = PWL627GZ4Y; GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; PRODUCT_BUNDLE_IDENTIFIER = slf.FleanUITests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; diff --git a/ios/extention/Resources/manifest.json b/ios/extention/Resources/manifest.json index d153b68..cac74e8 100644 --- a/ios/extention/Resources/manifest.json +++ b/ios/extention/Resources/manifest.json @@ -4,7 +4,7 @@ "name": "Flean Extension", "description": "Redirect Fandom wiki pages to independent mirrors.", - "version": "2.1.6", + "version": "2.2.0", "icons": { "48": "images/icon-48.png", diff --git a/ios/extention/Resources/scripts/wiki-data-manager.js b/ios/extention/Resources/scripts/wiki-data-manager.js index 7c40354..2d69ed3 100644 --- a/ios/extention/Resources/scripts/wiki-data-manager.js +++ b/ios/extention/Resources/scripts/wiki-data-manager.js @@ -163,21 +163,36 @@ export async function findMatchingWiki (urlString) { } try { article = decodeURIComponent(article) } catch { /* keep encoded */ } + // If the article is empty (wiki root) or matches the origin's main page, redirect to + // the destination's declared main page to honour cross-wiki naming differences. + if (wiki.destination_main_page) { + const normalize = title => (title || '').replace(/_/g, ' ').toLowerCase().trim() + if (!article || normalize(article) === normalize(originEntry.origin_main_page || '')) { + article = wiki.destination_main_page + } + } + // Build destination URL based on platform const destBase = wiki.destination_base_url .replace(/^https?:\/\//, '') .replace(/\/$/, '') const platform = (wiki.destination_platform || 'mediawiki').toLowerCase() let destPath = '' + const encodedArticle = encodeURIComponent(article.replace(/ /g, '_')) if (wiki.destination_content_path) { - destPath = wiki.destination_content_path - .replace('$1', encodeURIComponent(article.replace(/ /g, '_'))) + if (wiki.destination_content_path.includes('$1')) { + // Template-style path: replace the $1 placeholder with the article name + destPath = wiki.destination_content_path.replace('$1', encodedArticle) + } else { + // Prefix-style path (e.g. "/wiki/"): append the article name to the prefix + destPath = wiki.destination_content_path + encodedArticle + } } else if (platform === 'dokuwiki') { destPath = `/doku.php?id=${encodeURIComponent(article.replace(/ /g, '_').toLowerCase())}` } else { // Default: MediaWiki-style /wiki/ArticleName - destPath = `/wiki/${encodeURIComponent(article.replace(/ /g, '_'))}` + destPath = `/wiki/${encodedArticle}` } const destinationUrl = `https://${destBase}${destPath}${url.search}${url.hash}` diff --git a/mos/Flean Extension/Resources/manifest.json b/mos/Flean Extension/Resources/manifest.json index 0520cb8..98d9ed7 100644 --- a/mos/Flean Extension/Resources/manifest.json +++ b/mos/Flean Extension/Resources/manifest.json @@ -4,7 +4,7 @@ "name": "__MSG_extension_name__", "description": "__MSG_extension_description__", - "version": "2.1.6", + "version": "2.2.0", "icons": { "48": "images/icon-48.png", diff --git a/mos/Flean Extension/Resources/scripts/wiki-data-manager.js b/mos/Flean Extension/Resources/scripts/wiki-data-manager.js index 7c40354..2d69ed3 100644 --- a/mos/Flean Extension/Resources/scripts/wiki-data-manager.js +++ b/mos/Flean Extension/Resources/scripts/wiki-data-manager.js @@ -163,21 +163,36 @@ export async function findMatchingWiki (urlString) { } try { article = decodeURIComponent(article) } catch { /* keep encoded */ } + // If the article is empty (wiki root) or matches the origin's main page, redirect to + // the destination's declared main page to honour cross-wiki naming differences. + if (wiki.destination_main_page) { + const normalize = title => (title || '').replace(/_/g, ' ').toLowerCase().trim() + if (!article || normalize(article) === normalize(originEntry.origin_main_page || '')) { + article = wiki.destination_main_page + } + } + // Build destination URL based on platform const destBase = wiki.destination_base_url .replace(/^https?:\/\//, '') .replace(/\/$/, '') const platform = (wiki.destination_platform || 'mediawiki').toLowerCase() let destPath = '' + const encodedArticle = encodeURIComponent(article.replace(/ /g, '_')) if (wiki.destination_content_path) { - destPath = wiki.destination_content_path - .replace('$1', encodeURIComponent(article.replace(/ /g, '_'))) + if (wiki.destination_content_path.includes('$1')) { + // Template-style path: replace the $1 placeholder with the article name + destPath = wiki.destination_content_path.replace('$1', encodedArticle) + } else { + // Prefix-style path (e.g. "/wiki/"): append the article name to the prefix + destPath = wiki.destination_content_path + encodedArticle + } } else if (platform === 'dokuwiki') { destPath = `/doku.php?id=${encodeURIComponent(article.replace(/ /g, '_').toLowerCase())}` } else { // Default: MediaWiki-style /wiki/ArticleName - destPath = `/wiki/${encodeURIComponent(article.replace(/ /g, '_'))}` + destPath = `/wiki/${encodedArticle}` } const destinationUrl = `https://${destBase}${destPath}${url.search}${url.hash}` diff --git a/mos/Flean.xcodeproj/project.pbxproj b/mos/Flean.xcodeproj/project.pbxproj index 1514d96..2587a7d 100644 --- a/mos/Flean.xcodeproj/project.pbxproj +++ b/mos/Flean.xcodeproj/project.pbxproj @@ -379,7 +379,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = "Flean Extension/Flean_Extension.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = PWL627GZ4Y; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; @@ -392,7 +392,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -410,7 +410,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = "Flean Extension/Flean_Extension.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = PWL627GZ4Y; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; @@ -423,7 +423,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -564,7 +564,7 @@ CODE_SIGN_ENTITLEMENTS = Flean/Flean.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = PWL627GZ4Y; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; @@ -577,7 +577,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -603,7 +603,7 @@ CODE_SIGN_ENTITLEMENTS = Flean/Flean.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = PWL627GZ4Y; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; @@ -616,7 +616,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -639,11 +639,11 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = PWL627GZ4Y; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; PRODUCT_BUNDLE_IDENTIFIER = slf.FleanTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; @@ -657,11 +657,11 @@ buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = PWL627GZ4Y; GENERATE_INFOPLIST_FILE = YES; MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; PRODUCT_BUNDLE_IDENTIFIER = slf.FleanTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; @@ -674,10 +674,10 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = PWL627GZ4Y; GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; PRODUCT_BUNDLE_IDENTIFIER = slf.FleanUITests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO; @@ -690,10 +690,10 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 3; + CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = PWL627GZ4Y; GENERATE_INFOPLIST_FILE = YES; - MARKETING_VERSION = 2.1.6; + MARKETING_VERSION = 2.2.0; PRODUCT_BUNDLE_IDENTIFIER = slf.FleanUITests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = NO;