diff --git a/.github/workflows/SyndiKit.yml b/.github/workflows/SyndiKit.yml new file mode 100644 index 00000000..5bdcc29d --- /dev/null +++ b/.github/workflows/SyndiKit.yml @@ -0,0 +1,270 @@ +name: SyndiKit + +# Standalone CI for this BrightDigit Swift package on Swift 6.4 (the BrightDigit +# CI template). These five workflows are kept byte-identical except the name above; +# the only per-package difference is externalized to the ENABLE_WASM repo variable. +# Linux + wasm run in the nightly-6.4 container; macOS + the Apple-platform suite +# run on the self-hosted runner with /Applications/Xcode-beta.app (Xcode 27 / +# Swift 6.4); Windows on a swift.org nightly snapshot; Android via a swift.org SDK +# bundle. The wasm step is gated on ENABLE_WASM — set it to 'false' where a +# dependency can't build for wasm (e.g. Yams). +on: + push: + branches: [main] + tags: ['v*.*.*'] + paths-ignore: + - '**.md' + - 'LICENSE' + pull_request: + paths-ignore: + - '**.md' + - 'LICENSE' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +jobs: + build-ubuntu: + name: Build on Ubuntu + needs: configure + runs-on: ubuntu-latest + container: swiftlang/swift:nightly-6.4.x-noble + if: ${{ !contains(github.event.head_commit.message, 'ci skip') }} + # Ubuntu variants from a matrix (configure → ubuntu-type): standard ('') always; + # wasm + wasm-embedded when ENABLE_WASM != 'false'. Both wasm variants share the + # same nightly-6.4.x SDK bundle. OpenAPI packages guard URLSession behind + # #if !os(WASI) so the wasm/embedded legs build. + strategy: + fail-fast: false + matrix: + type: ${{ fromJSON(needs.configure.outputs.ubuntu-type) }} + steps: + - uses: actions/checkout@v6 + - uses: brightdigit/swift-build@v1 + id: build + with: + type: ${{ matrix.type }} + # wasm / wasm-embedded are build-only: WasmKit doesn't mount the Foundation + # resource bundles the tests load, and embedded hits OpenAPIRuntime keypath + # limits at runtime. The standard ('') leg runs the full suite + coverage. + build-only: ${{ matrix.type != '' }} + wasm-sdk-url: https://download.swift.org/swift-6.4.x-branch/wasm-sdk/swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-06-15-a/swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-06-15-a_wasm.artifactbundle.tar.gz + wasm-sdk-checksum: c014a0162de6eeeef4f07904ce096ccee5405c1478a12c99a3a9750bd42d7702 + wasm-swift-flags: >- + -Xcc -D_WASI_EMULATED_SIGNAL -Xcc -D_WASI_EMULATED_MMAN + -Xlinker -lwasi-emulated-signal -Xlinker -lwasi-emulated-mman + -Xlinker -lwasi-emulated-getpid + -Xlinker --initial-memory=536870912 -Xlinker --max-memory=536870912 + - name: Install curl (required by Codecov uploader) + if: steps.build.outputs.contains-code-coverage == 'true' + run: | + if ! command -v curl &> /dev/null; then + apt-get update -q + apt-get install -y --no-install-recommends curl ca-certificates + fi + # brightdigit fork of swift-coverage-action: upstream @v5 can't pair the + # profdata with the test binary under Swift 6.4's swiftbuild layout + # (.so + -test-runner, no .xctest) — issue #92. Pinned by SHA. + - uses: brightdigit/swift-coverage-action@2f8538f723b99ab2406ac3a0e5b3355a9de4cf6c + if: steps.build.outputs.contains-code-coverage == 'true' + id: coverage-files + with: + search-paths: .build + fail-on-empty-output: true + - name: Upload coverage to Codecov + if: steps.build.outputs.contains-code-coverage == 'true' + uses: codecov/codecov-action@v7 + with: + fail_ci_if_error: false + flags: noble,swift-6.4 + verbose: true + token: ${{ secrets.CODECOV_TOKEN }} + files: ${{ join(fromJSON(steps.coverage-files.outputs.files), ',') }} + + configure: + name: Configure Matrix + runs-on: ubuntu-latest + outputs: + full-matrix: ${{ steps.check.outputs.full }} + run-windows: ${{ steps.check.outputs.windows }} + ubuntu-type: ${{ steps.check.outputs.ubuntu-type }} + steps: + - uses: actions/checkout@v6 + - id: check + name: Determine matrix scope + run: | + # Three tiers: small set (build-ubuntu[+wasm]/build-macos/lint, always) < + # full-matrix (macOS-platforms/android) < +Windows. full-matrix runs on + # main / semver / dispatch / PRs into main or semver. Windows is the most + # expensive leg, so run-windows is the same MINUS PRs into semver branches. + FULL=false; WIN=false + REF="${{ github.ref }}"; EVENT="${{ github.event_name }}"; BASE_REF="${{ github.base_ref }}" + if [[ "$REF" == "refs/heads/main" ]]; then FULL=true; WIN=true + elif [[ "$REF" =~ ^refs/heads/v?[0-9]+\.[0-9]+\.[0-9]+ ]]; then FULL=true; WIN=true + elif [[ "$EVENT" == "workflow_dispatch" ]]; then FULL=true; WIN=true + elif [[ "$EVENT" == "pull_request" ]]; then + if [[ "$BASE_REF" == "main" ]]; then FULL=true; WIN=true + elif [[ "$BASE_REF" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+ ]]; then FULL=true + fi + fi + echo "full=$FULL" >> "$GITHUB_OUTPUT" + echo "windows=$WIN" >> "$GITHUB_OUTPUT" + # Ubuntu build variants: standard ('') always; wasm + wasm-embedded + # unless the package disables wasm via ENABLE_WASM (e.g. Yams). + if [[ "${{ vars.ENABLE_WASM }}" != "false" ]]; then + echo 'ubuntu-type=["","wasm","wasm-embedded"]' >> "$GITHUB_OUTPUT" + else + echo 'ubuntu-type=[""]' >> "$GITHUB_OUTPUT" + fi + + # macOS on Swift 6.4 via the self-hosted runner with /Applications/Xcode-beta.app. + build-macos: + name: Build on macOS + runs-on: [self-hosted, macOS] + if: ${{ !contains(github.event.head_commit.message, 'ci skip') }} + steps: + - uses: actions/checkout@v6 + - uses: brightdigit/swift-build@v1 + id: build + with: + xcode: "/Applications/Xcode-beta.app" + - name: Process coverage + if: steps.build.outputs.contains-code-coverage == 'true' + uses: sersoft-gmbh/swift-coverage-action@v5 + with: + search-paths: .build + - name: Upload coverage to Codecov + if: steps.build.outputs.contains-code-coverage == 'true' + uses: codecov/codecov-action@v7 + with: + fail_ci_if_error: false + flags: spm,macos + token: ${{ secrets.CODECOV_TOKEN }} + + # Windows nightly 6.4 via a swift.org development snapshot (compnerd/gha-setup-swift + # under swift-build), on hosted runners. Own tier (run-windows): the most + # expensive leg, so it runs on main / semver / dispatch / PRs into main, but NOT + # PRs into semver branches. Bump the snapshot id periodically (swift.org GCs them). + build-windows: + name: Build on Windows + needs: configure + if: ${{ needs.configure.outputs.run-windows == 'true' }} + runs-on: ${{ matrix.runs-on }} + strategy: + fail-fast: false + matrix: + runs-on: [windows-2022, windows-2025] + swift: + - version: swift-6.4.x-branch + build: 6.4.x-DEVELOPMENT-SNAPSHOT-2026-06-01-a + steps: + - uses: actions/checkout@v6 + - uses: brightdigit/swift-build@v1 + id: build + with: + windows-swift-version: ${{ matrix.swift.version }} + windows-swift-build: ${{ matrix.swift.build }} + + # Full Apple-platform suite (iOS/watchOS/tvOS) on Swift 6.4, on the self-hosted + # runner with /Applications/Xcode-beta.app (Xcode 27), using the 27.0 simulator + # runtimes installed there. Blocking leg; simulator runs on the nightly + # toolchain are the most fragile leg. Bump deviceName/osVersion as Xcode-beta moves. + # The watchOS leg is gated on the ENABLE_WATCHOS repo variable (set 'false' to skip it + # where the watchOS-27 SDK rejects deps inferring 8.0 — SwiftPM #10188; see + # brightdigit.com#119). iOS/tvOS always run. + build-macos-platforms: + name: Build on macOS (Platforms) + needs: configure + if: ${{ needs.configure.outputs.full-matrix == 'true' }} + runs-on: [self-hosted, macOS] + strategy: + fail-fast: false + matrix: + include: + - { type: ios, deviceName: "iPhone 17 Pro", osVersion: "27.0" } + - { type: watchos, deviceName: "Apple Watch Ultra 3 (49mm)", osVersion: "27.0" } + - { type: tvos, deviceName: "Apple TV 4K (3rd generation)", osVersion: "27.0" } + steps: + - uses: actions/checkout@v6 + - name: Build and Test + id: build + # watchOS disabled where ENABLE_WATCHOS=false (SwiftPM #10188, watchOS-27 + # deployment-target clamp); re-enable per brightdigit.com#119. + if: ${{ !(matrix.type == 'watchos' && vars.ENABLE_WATCHOS == 'false') }} + uses: brightdigit/swift-build@v1 + with: + type: ${{ matrix.type }} + xcode: "/Applications/Xcode-beta.app" + deviceName: ${{ matrix.deviceName }} + osVersion: ${{ matrix.osVersion }} + - name: Process coverage + if: steps.build.outputs.contains-code-coverage == 'true' + uses: sersoft-gmbh/swift-coverage-action@v5 + with: + search-paths: .build + - name: Upload coverage to Codecov + if: steps.build.outputs.contains-code-coverage == 'true' + uses: codecov/codecov-action@v7 + with: + fail_ci_if_error: false + token: ${{ secrets.CODECOV_TOKEN }} + flags: ${{ format('{0}{1}', matrix.type, matrix.osVersion) }} + + # Android on nightly 6.4 via a swift.org swift-6.4.x-branch snapshot SDK bundle + # (custom-sdk-url path through swift-build → skiptools/swift-android-action). + # Blocking leg; build-only (android-run-tests: false). + # Bump the snapshot id periodically. + build-android: + name: Build on Android + needs: configure + if: ${{ needs.configure.outputs.full-matrix == 'true' }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + android-api-level: [34] + steps: + - uses: actions/checkout@v6 + - name: Free disk space + uses: jlumbroso/free-disk-space@v1.3.1 + with: + tool-cache: false + android: false + dotnet: true + haskell: true + large-packages: true + docker-images: true + swap-storage: true + - uses: brightdigit/swift-build@v1 + with: + type: android + android-swift-version: 6.4.x-DEVELOPMENT-SNAPSHOT-2026-06-15-a + android-sdk-url: https://download.swift.org/swift-6.4.x-branch/android-sdk/swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-06-15-a/swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-06-15-a_android.artifactbundle.tar.gz + android-sdk-id: swift-6.4.x-DEVELOPMENT-SNAPSHOT-2026-06-15-a_android + android-api-level: ${{ matrix.android-api-level }} + android-run-tests: false + + lint: + name: Linting + if: ${{ !cancelled() && !failure() && !contains(github.event.head_commit.message, 'ci skip') }} + needs: [build-ubuntu, build-macos, build-windows, build-macos-platforms] + runs-on: ubuntu-latest + container: swiftlang/swift:nightly-6.4.x-noble + steps: + - name: Install curl (required by mise-action) + run: | + apt-get update -q + apt-get install -y --no-install-recommends curl ca-certificates + - uses: actions/checkout@v6 + - uses: jdx/mise-action@v4 + env: + MISE_HTTP_TIMEOUT: 300s + MISE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + cache: true + - name: Lint + run: ./Scripts/lint.sh + env: + LINT_MODE: STRICT diff --git a/.github/workflows/syndikit.yml b/.github/workflows/syndikit.yml deleted file mode 100644 index 40c43e45..00000000 --- a/.github/workflows/syndikit.yml +++ /dev/null @@ -1,380 +0,0 @@ -name: SyndiKit -on: - push: - branches: - - main - - 'v[0-9]+.[0-9]+.[0-9]+' - paths-ignore: - - '**.md' - - 'docs/**' - - 'LICENSE' - - '.github/ISSUE_TEMPLATE/**' - pull_request: - paths-ignore: - - '**.md' - - 'docs/**' - - 'LICENSE' - - '.github/ISSUE_TEMPLATE/**' - workflow_dispatch: - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }} - cancel-in-progress: true - -env: - PACKAGE_NAME: SyndiKit - -jobs: - configure: - name: Configure Matrix - runs-on: ubuntu-latest - outputs: - full-matrix: ${{ steps.matrix.outputs.full-matrix }} - ubuntu-os: ${{ steps.matrix.outputs.ubuntu-os }} - ubuntu-swift: ${{ steps.matrix.outputs.ubuntu-swift }} - ubuntu-type: ${{ steps.matrix.outputs.ubuntu-type }} - steps: - - id: check - name: Determine matrix scope - run: | - FULL=false - REF="${{ github.ref }}" - EVENT="${{ github.event_name }}" - BASE_REF="${{ github.base_ref }}" - if [[ "$REF" == "refs/heads/main" ]]; then - FULL=true - elif [[ "$REF" =~ ^refs/heads/v?[0-9]+\.[0-9]+\.[0-9]+ ]]; then - FULL=true - elif [[ "$EVENT" == "workflow_dispatch" ]]; then - FULL=true - elif [[ "$EVENT" == "pull_request" ]]; then - if [[ "$BASE_REF" == "main" || "$BASE_REF" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+ ]]; then - FULL=true - fi - fi - echo "full=$FULL" >> "$GITHUB_OUTPUT" - - id: matrix - name: Build matrix values - run: | - if [[ "${{ steps.check.outputs.full }}" == "true" ]]; then - echo 'full-matrix=true' >> "$GITHUB_OUTPUT" - echo 'ubuntu-os=["noble","jammy"]' >> "$GITHUB_OUTPUT" - echo 'ubuntu-swift=[{"version":"5.10"},{"version":"6.0"},{"version":"6.1"},{"version":"6.2"},{"version":"6.3"}]' >> "$GITHUB_OUTPUT" - echo 'ubuntu-type=["","wasm","wasm-embedded"]' >> "$GITHUB_OUTPUT" - else - echo 'full-matrix=false' >> "$GITHUB_OUTPUT" - echo 'ubuntu-os=["noble"]' >> "$GITHUB_OUTPUT" - echo 'ubuntu-swift=[{"version":"6.3"}]' >> "$GITHUB_OUTPUT" - echo 'ubuntu-type=[""]' >> "$GITHUB_OUTPUT" - fi - - build-ubuntu: - name: Build on Ubuntu - needs: configure - runs-on: ubuntu-latest - container: swift:${{ matrix.swift.version }}-${{ matrix.os }} - strategy: - matrix: - os: ${{ fromJSON(needs.configure.outputs.ubuntu-os) }} - swift: ${{ fromJSON(needs.configure.outputs.ubuntu-swift) }} - type: ${{ fromJSON(needs.configure.outputs.ubuntu-type) }} - exclude: - - swift: {version: "5.10"} - type: wasm - - swift: {version: "5.10"} - type: wasm-embedded - - swift: {version: "6.0"} - type: wasm - - swift: {version: "6.0"} - type: wasm-embedded - - swift: {version: "6.1"} - type: wasm - - swift: {version: "6.1"} - type: wasm-embedded - steps: - - uses: actions/checkout@v6 - - id: build - uses: brightdigit/swift-build@v1 - with: - type: ${{ matrix.type }} - skip-package-resolved: ${{ contains(matrix.swift.version, '5.') }} - - name: Install curl - if: steps.build.outputs.contains-code-coverage == 'true' - run: | - if ! command -v curl &> /dev/null; then - apt-get update -q - apt-get install -y curl - fi - - name: Process Coverage - if: steps.build.outputs.contains-code-coverage == 'true' - uses: sersoft-gmbh/swift-coverage-action@v5 - with: - fail-on-empty-output: true - - name: Upload coverage to Codecov - if: steps.build.outputs.contains-code-coverage == 'true' - uses: codecov/codecov-action@v6 - with: - token: ${{ secrets.CODECOV_TOKEN }} - flags: spm,${{ matrix.os }},${{ matrix.swift.version }} - fail_ci_if_error: true - - build-macos: - name: Build on macOS - runs-on: ${{ matrix.runs-on }} - strategy: - matrix: - include: - # SPM Build Matrix - Xcode 15.4 - - runs-on: macos-14 - xcode: "/Applications/Xcode_15.4.app" - - # SPM Build Matrix - Xcode 16.4 - - runs-on: macos-15 - xcode: "/Applications/Xcode_16.4.app" - - # SPM Build Matrix - Xcode 26.4 - - runs-on: macos-26 - xcode: "/Applications/Xcode_26.4.app" - - # macOS Build Matrix - Xcode 15.4 - - type: macos - runs-on: macos-14 - xcode: "/Applications/Xcode_15.4.app" - - # macOS Build Matrix - Xcode 16.4 - - type: macos - runs-on: macos-15 - xcode: "/Applications/Xcode_16.4.app" - - # macOS Build Matrix - Xcode 26.4 - - type: macos - runs-on: macos-26 - xcode: "/Applications/Xcode_26.4.app" - - # iOS Build Matrix - Xcode 15.4 - - type: ios - runs-on: macos-14 - xcode: "/Applications/Xcode_15.4.app" - deviceName: "iPhone 15 Pro" - osVersion: "17.5" - - # iOS Build Matrix - Xcode 16.4 - - type: ios - runs-on: macos-15 - xcode: "/Applications/Xcode_16.4.app" - deviceName: "iPhone 16" - osVersion: "18.5" - - # iOS Build Matrix - Xcode 26.4 - - type: ios - runs-on: macos-26 - xcode: "/Applications/Xcode_26.4.app" - deviceName: "iPhone 17" - osVersion: "26.4" - download-platform: true - - # watchOS Build Matrix - Xcode 15.4 - - type: watchos - runs-on: macos-14 - xcode: "/Applications/Xcode_15.4.app" - deviceName: "Apple Watch Series 9 (41mm)" - osVersion: "10.5" - - # watchOS Build Matrix - Xcode 16.4 - - type: watchos - runs-on: macos-15 - xcode: "/Applications/Xcode_16.4.app" - deviceName: "Apple Watch Ultra 2 (49mm)" - osVersion: "11.5" - - # watchOS Build Matrix - Xcode 26.4 - - type: watchos - runs-on: macos-26 - xcode: "/Applications/Xcode_26.4.app" - deviceName: "Apple Watch Ultra 3 (49mm)" - osVersion: "26.4" - download-platform: true - - # tvOS Build Matrix - Xcode 16.4 - - type: tvos - runs-on: macos-15 - xcode: "/Applications/Xcode_16.4.app" - deviceName: "Apple TV 4K (3rd generation)" - osVersion: "18.5" - - # tvOS Build Matrix - Xcode 26.4 - - type: tvos - runs-on: macos-26 - xcode: "/Applications/Xcode_26.4.app" - deviceName: "Apple TV 4K (3rd generation)" - osVersion: "26.4" - download-platform: true - - # visionOS Build Matrix - Xcode 16.4 - - type: visionos - runs-on: macos-15 - xcode: "/Applications/Xcode_16.4.app" - deviceName: "Apple Vision Pro" - osVersion: "2.5" - - # visionOS Build Matrix - Xcode 26.4 - - type: visionos - runs-on: macos-26 - xcode: "/Applications/Xcode_26.4.app" - deviceName: "Apple Vision Pro" - osVersion: "26.4" - download-platform: true - - steps: - - uses: actions/checkout@v6 - - - name: Disable Xcode macro fingerprint validation - if: ${{ contains(matrix.xcode, 'Xcode_15.4') && matrix.type != '' }} - run: defaults write com.apple.dt.Xcode IDESkipMacroFingerprintValidation -bool YES - - - id: build - name: Build and Test - uses: brightdigit/swift-build@v1 - with: - scheme: ${{ env.PACKAGE_NAME }} - type: ${{ matrix.type }} - xcode: ${{ matrix.xcode }} - deviceName: ${{ matrix.deviceName }} - osVersion: ${{ matrix.osVersion }} - download-platform: ${{ matrix.download-platform }} - build-only: ${{ contains(matrix.xcode, 'Xcode_15.4') && matrix.type != '' }} - skip-package-resolved: ${{ contains(matrix.xcode, 'Xcode_15.4') }} - - - name: Process Coverage - if: ${{ steps.build.outputs.contains-code-coverage == 'true' }} - uses: sersoft-gmbh/swift-coverage-action@v5 - with: - fail-on-empty-output: true - search-paths: | - ./.build - /Users/runner/work/_temp/DerivedData - - - name: Upload Coverage - if: ${{ steps.build.outputs.contains-code-coverage == 'true' }} - uses: codecov/codecov-action@v6 - with: - token: ${{ secrets.CODECOV_TOKEN }} - flags: ${{ matrix.type && format('{0}{1}', matrix.type, matrix.osVersion) || 'spm' }} - fail_ci_if_error: true - - build-windows: - name: Build on Windows - needs: [configure] - if: needs.configure.outputs.full-matrix == 'true' - runs-on: ${{ matrix.runs-on }} - strategy: - matrix: - runs-on: [windows-2022, windows-2025] - swift: - - version: swift-6.1-release - build: 6.1-RELEASE - - version: swift-6.2-release - build: 6.2-RELEASE - - version: swift-6.3-release - build: 6.3-RELEASE - steps: - - uses: actions/checkout@v6 - - id: build - uses: brightdigit/swift-build@v1 - with: - windows-swift-version: ${{ matrix.swift.version }} - windows-swift-build: ${{ matrix.swift.build }} - - name: Upload coverage to Codecov - if: steps.build.outputs.contains-code-coverage == 'true' - uses: codecov/codecov-action@v6 - with: - token: ${{ secrets.CODECOV_TOKEN }} - flags: windows,${{ matrix.swift.version }} - fail_ci_if_error: true - - build-android: - name: Build on Android - needs: [configure] - if: needs.configure.outputs.full-matrix == 'true' - runs-on: ubuntu-latest - strategy: - matrix: - swift: - - version: "6.1" - - version: "6.2" - - version: "6.3" - android-api-level: [28, 33, 36] - steps: - - uses: actions/checkout@v6 - - - name: Free Disk Space - run: | - sudo rm -rf /usr/share/dotnet - sudo rm -rf /opt/ghc - sudo rm -rf /usr/local/share/boost - sudo rm -rf "$AGENT_TOOLSDIRECTORY" - sudo apt-get clean - sudo docker image prune --all --force - - - id: build - uses: brightdigit/swift-build@v1 - with: - type: android - android-swift-version: ${{ matrix.swift.version }} - android-api-level: ${{ matrix.android-api-level }} - android-run-tests: true - android-copy-files: Data/ - - name: Upload coverage to Codecov - if: steps.build.outputs.contains-code-coverage == 'true' - uses: codecov/codecov-action@v6 - with: - token: ${{ secrets.CODECOV_TOKEN }} - flags: android,${{ matrix.swift.version }},${{ matrix.android-api-level }} - fail_ci_if_error: true - - lint: - name: Linting - if: ${{ always() && !cancelled() && !failure() }} - runs-on: ubuntu-latest - needs: [build-ubuntu, build-macos, build-windows, build-android] - env: - MINT_PATH: .mint/lib - MINT_LINK_PATH: .mint/bin - steps: - - uses: actions/checkout@v6 - - name: Cache mint - id: cache-mint - uses: actions/cache@v4 - env: - cache-name: cache - with: - path: | - .mint - Mint - key: ${{ runner.os }}-mint-${{ hashFiles('**/Mintfile') }} - restore-keys: | - ${{ runner.os }}-mint- - - name: Install mint - if: steps.cache-mint.outputs.cache-hit == '' - run: | - git clone https://github.com/yonaskolb/Mint.git - cd Mint - swift run mint install yonaskolb/mint - - name: Lint - run: ./Scripts/lint.sh - - swift-source-compat-suite: - name: Test Swift 6.x For Source Compatibility Suite - runs-on: ubuntu-latest - strategy: - matrix: - container: - - swift:6.0 - - swift:6.1 - - swift:6.2 - - swift:6.3 - container: ${{ matrix.container }} - steps: - - uses: actions/checkout@v6 - - name: Run Swift 6.x tests - run: swift build --disable-sandbox --verbose --configuration release -Xswiftc -swift-version -Xswiftc 6 diff --git a/.hound.yml b/.hound.yml deleted file mode 100644 index 6941f639..00000000 --- a/.hound.yml +++ /dev/null @@ -1,2 +0,0 @@ -swiftlint: - config_file: .swiftlint.yml diff --git a/.mise.toml b/.mise.toml new file mode 100644 index 00000000..87bc056c --- /dev/null +++ b/.mise.toml @@ -0,0 +1,16 @@ +[settings] +# Enable experimental features (required for the spm backend) +experimental = true + +[tools] +# Swift development tools (managed via mise) +# 604.x aligns swift-format (and its swift-syntax) with the Swift 6.4 toolchain. +# Only one 604 tag exists so far; bump when a newer 604 prerelease/release lands. +"spm:swiftlang/swift-format" = "604.0.0-prerelease-2025-12-17" +"aqua:realm/SwiftLint" = "0.63.2" +"spm:peripheryapp/periphery" = "3.7.4" + +[tasks] +swift-format = "swift-format" +swiftlint = "swiftlint" +periphery = "periphery" diff --git a/.swift-format b/.swift-format index a657e6cc..257f5557 100644 --- a/.swift-format +++ b/.swift-format @@ -1,12 +1,12 @@ { "fileScopedDeclarationPrivacy" : { - "accessLevel" : "private" + "accessLevel" : "fileprivate" }, - "indentConditionalCompilationBlocks" : true, - "indentSwitchCaseLabels" : false, "indentation" : { "spaces" : 2 }, + "indentConditionalCompilationBlocks" : true, + "indentSwitchCaseLabels" : false, "lineBreakAroundMultilineExpressionChainComponents" : false, "lineBreakBeforeControlFlowKeywords" : false, "lineBreakBeforeEachArgument" : false, @@ -29,13 +29,13 @@ "BeginDocumentationCommentWithOneLineSummary" : false, "DoNotUseSemicolons" : true, "DontRepeatTypeInStaticProperties" : true, - "FileScopedDeclarationPrivacy" : true, + "FileScopedDeclarationPrivacy" : false, "FullyIndirectEnum" : true, "GroupNumericLiterals" : true, "IdentifiersMustBeASCII" : true, - "NeverForceUnwrap" : false, - "NeverUseForceTry" : false, - "NeverUseImplicitlyUnwrappedOptionals" : false, + "NeverForceUnwrap" : true, + "NeverUseForceTry" : true, + "NeverUseImplicitlyUnwrappedOptionals" : true, "NoAccessLevelOnExtensionDeclaration" : true, "NoAssignmentInExpressions" : true, "NoBlockComments" : true, @@ -56,13 +56,13 @@ "TypeNamesShouldBeCapitalized" : true, "UseEarlyExits" : false, "UseExplicitNilCheckInConditions" : true, - "UseLetInEveryBoundCaseVariable" : false, + "UseLetInEveryBoundCaseVariable" : true, "UseShorthandTypeNames" : true, "UseSingleLinePropertyGetter" : true, "UseSynthesizedInitializer" : true, "UseTripleSlashForDocumentationComments" : true, "UseWhereClausesInForLoops" : true, - "ValidateDocumentationComments" : false + "ValidateDocumentationComments" : true }, "spacesAroundRangeFormationOperators" : false, "tabWidth" : 2, diff --git a/.swiftformat b/.swiftformat deleted file mode 100644 index 2601bf7a..00000000 --- a/.swiftformat +++ /dev/null @@ -1,7 +0,0 @@ ---indent 2 ---header strip ---commas inline ---disable wrapMultilineStatementBraces ---extensionacl on-declarations ---decimalgrouping 3,4 ---exclude .build, DerivedData diff --git a/.swiftlint.yml b/.swiftlint.yml index 3288a2ae..4ccdb85d 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -40,7 +40,7 @@ opt_in_rules: - legacy_random - literal_expression_end_indentation - lower_acl_than_parent -# - missing_docs + - missing_docs - modifier_order - multiline_arguments - multiline_arguments_brackets @@ -52,6 +52,7 @@ opt_in_rules: - nslocalizedstring_require_bundle - number_separator - object_literal + - one_declaration_per_file - operator_usage_whitespace - optional_enum_case_matching - overridden_super_call @@ -88,44 +89,47 @@ opt_in_rules: - xct_specific_matcher - yoda_condition analyzer_rules: - - unused_import + - unused_import - unused_declaration cyclomatic_complexity: - 6 - - 9 + - 12 file_length: - - 225 - - 550 + warning: 225 + error: 300 function_body_length: - - 30 - 50 + - 76 function_parameter_count: 8 line_length: - - 90 - - 90 + - 108 + - 200 +closure_body_length: + - 50 + - 60 type_name: - excluded: - - iTunesDuration - - iTunesEpisode - - iTunesOwner - - iTunesImage + min_length: 3 + max_length: + warning: 50 + error: 60 identifier_name: excluded: - id + - no excluded: - - Tests - DerivedData - .build + - .swiftpm + - "*/.swiftpm" + - "*/.build" - Mint + - Examples + - Packages + - Package.swift indentation_width: indentation_width: 2 file_name: severity: error - excluded: - - iTunesImage - - iTunesDuration - - iTunesEpisode - - iTunesOwner fatal_error_message: severity: error disabled_rules: @@ -135,4 +139,11 @@ disabled_rules: - closure_parameter_position - trailing_comma - opening_brace - - inclusive_language + - optional_data_string_conversion + - pattern_matching_keywords +custom_rules: + no_unchecked_sendable: + name: "No Unchecked Sendable" + regex: '@unchecked\s+Sendable' + message: "Use proper Sendable conformance instead of @unchecked Sendable to maintain strict concurrency safety" + severity: error diff --git a/Package.swift b/Package.swift index e0d79c72..3b192d0b 100644 --- a/Package.swift +++ b/Package.swift @@ -6,7 +6,7 @@ import PackageDescription let package = Package( name: "SyndiKit", platforms: [ - .macOS(.v10_15), + .macOS(.v13), .iOS(.v13), .watchOS(.v6), .tvOS(.v13) diff --git a/Scripts/header.sh b/Scripts/header.sh index 4ed74462..c571c189 100755 --- a/Scripts/header.sh +++ b/Scripts/header.sh @@ -44,7 +44,7 @@ header_template="// // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the \"Software\"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -54,7 +54,7 @@ header_template="// // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -66,6 +66,12 @@ header_template="// # Loop through each Swift file in the specified directory and subdirectories find "$directory" -type f -name "*.swift" | while read -r file; do + # Skip files in the Generated directory + if [[ "$file" == *"/Generated/"* ]]; then + echo "Skipping $file (generated file)" + continue + fi + # Check if the first line is the swift-format-ignore indicator first_line=$(head -n 1 "$file") if [[ "$first_line" == "// swift-format-ignore-file" ]]; then @@ -90,9 +96,9 @@ find "$directory" -type f -name "*.swift" | while read -r file; do # Add the header to the cleaned file (echo "$header"; echo; cat temp_file) > "$file" - + # Remove the temporary file rm temp_file done -echo "Headers added or files skipped appropriately across all Swift files in the directory and subdirectories." \ No newline at end of file +echo "Headers added or files skipped appropriately across all Swift files in the directory and subdirectories." diff --git a/Scripts/lint.sh b/Scripts/lint.sh index 9f7e29c0..d270b134 100755 --- a/Scripts/lint.sh +++ b/Scripts/lint.sh @@ -1,78 +1,101 @@ #!/bin/bash -set -e # Exit on any error +# Remove set -e to allow script to continue running +# set -e # Exit on any error ERRORS=0 run_command() { - if [ "$LINT_MODE" = "STRICT" ]; then - "$@" || ERRORS=$((ERRORS + 1)) - else - "$@" - fi + "$@" || ERRORS=$((ERRORS + 1)) } +if [ "$LINT_MODE" = "INSTALL" ]; then + exit +fi + echo "LintMode: $LINT_MODE" # More portable way to get script directory if [ -z "$SRCROOT" ]; then - SCRIPT_DIR=$(dirname "$(readlink -f "$0")") - PACKAGE_DIR="${SCRIPT_DIR}/.." + SCRIPT_DIR=$(dirname "$(readlink -f "$0")") + PACKAGE_DIR="${SCRIPT_DIR}/.." else - PACKAGE_DIR="${SRCROOT}" + PACKAGE_DIR="${SRCROOT}" +fi + +# Detect if mise is available +# Check common installation paths for mise +MISE_PATHS=( + "/opt/homebrew/bin/mise" + "/usr/local/bin/mise" + "$HOME/.local/bin/mise" +) + +MISE_BIN="" +for mise_path in "${MISE_PATHS[@]}"; do + if [ -x "$mise_path" ]; then + MISE_BIN="$mise_path" + break + fi +done + +# Fallback to PATH lookup +if [ -z "$MISE_BIN" ] && command -v mise &> /dev/null; then + MISE_BIN="mise" fi -# Detect OS and set paths accordingly -if [ "$(uname)" = "Darwin" ]; then - DEFAULT_MINT_PATH="/opt/homebrew/bin/mint" -elif [ "$(uname)" = "Linux" ] && [ -n "$GITHUB_ACTIONS" ]; then - DEFAULT_MINT_PATH="$GITHUB_WORKSPACE/Mint/.mint/bin/mint" -elif [ "$(uname)" = "Linux" ]; then - DEFAULT_MINT_PATH="/usr/local/bin/mint" +if [ -n "$MISE_BIN" ]; then + TOOL_CMD="$MISE_BIN exec --" else - echo "Unsupported operating system" + echo "Error: mise is not installed" + echo "Install mise: https://mise.jdx.dev/getting-started.html" + echo "Checked paths: ${MISE_PATHS[*]}" exit 1 fi -# Use environment MINT_CMD if set, otherwise use default path -MINT_CMD=${MINT_CMD:-$DEFAULT_MINT_PATH} - -export MINT_PATH="$PACKAGE_DIR/.mint" -MINT_ARGS="-n -m $PACKAGE_DIR/Mintfile --silent" -MINT_RUN="$MINT_CMD run $MINT_ARGS" - if [ "$LINT_MODE" = "NONE" ]; then exit elif [ "$LINT_MODE" = "STRICT" ]; then - SWIFTFORMAT_OPTIONS="--strict --configuration .swift-format" + SWIFTFORMAT_LINT_OPTIONS="--strict" SWIFTLINT_OPTIONS="--strict" -else - SWIFTFORMAT_OPTIONS="--configuration .swift-format" +else + SWIFTFORMAT_LINT_OPTIONS="" SWIFTLINT_OPTIONS="" fi pushd $PACKAGE_DIR -run_command $MINT_CMD bootstrap -m Mintfile -if [ "$LINT_MODE" = "INSTALL" ]; then - exit -fi +# Bootstrap tools (mise will install based on .mise.toml) +run_command "$MISE_BIN" install if [ -z "$CI" ]; then - run_command $MINT_RUN swift-format format $SWIFTFORMAT_OPTIONS --recursive --parallel --in-place Sources Tests - run_command $MINT_RUN swiftlint --fix + run_command $TOOL_CMD swift-format format --configuration .swift-format --recursive --parallel --in-place Sources Tests + run_command $TOOL_CMD swiftlint --fix fi if [ -z "$FORMAT_ONLY" ]; then - run_command $MINT_RUN swift-format lint --configuration .swift-format --recursive --parallel $SWIFTFORMAT_OPTIONS Sources Tests || exit 1 - run_command $MINT_RUN swiftlint lint $SWIFTLINT_OPTIONS || exit 1 + run_command $TOOL_CMD swift-format lint --configuration .swift-format --recursive --parallel $SWIFTFORMAT_LINT_OPTIONS Sources Tests + run_command $TOOL_CMD swiftlint lint $SWIFTLINT_OPTIONS + # Check for compilation errors + run_command swift build --build-tests fi -$PACKAGE_DIR/Scripts/header.sh -d $PACKAGE_DIR/Sources -c "Leo Dion" -o "BrightDigit" -p "SyndiKit" - -run_command $MINT_RUN swiftlint lint $SWIFTLINT_OPTIONS +# header.sh rewrites file headers in place, so it only runs locally — never in CI. +if [ -z "$CI" ]; then + $PACKAGE_DIR/Scripts/header.sh -d $PACKAGE_DIR/Sources -c "Leo Dion" -o "BrightDigit" -p "SyndiKit" +fi -run_command $MINT_RUN swift-format lint --recursive --parallel $SWIFTFORMAT_OPTIONS Sources Tests -#$MINT_RUN periphery scan $PERIPHERY_OPTIONS --disable-update-check +if [ -z "$CI" ]; then + run_command $TOOL_CMD periphery scan $PERIPHERY_OPTIONS --disable-update-check +fi popd + +# Exit with error code if any errors occurred +if [ $ERRORS -gt 0 ]; then + echo "Linting completed with $ERRORS error(s)" + exit 1 +else + echo "Linting completed successfully" + exit 0 +fi diff --git a/Sources/SyndiKit/Character.swift b/Sources/SyndiKit/Character.swift index fec6974b..6135aaa1 100644 --- a/Sources/SyndiKit/Character.swift +++ b/Sources/SyndiKit/Character.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Collection.swift b/Sources/SyndiKit/Collection.swift index ada8a78a..455e4427 100644 --- a/Sources/SyndiKit/Collection.swift +++ b/Sources/SyndiKit/Collection.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Common/Author.swift b/Sources/SyndiKit/Common/Author.swift index c5bb79a6..d27c3181 100644 --- a/Sources/SyndiKit/Common/Author.swift +++ b/Sources/SyndiKit/Common/Author.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Common/EntryCategory.swift b/Sources/SyndiKit/Common/EntryCategory.swift index 6916b17f..abfceec5 100644 --- a/Sources/SyndiKit/Common/EntryCategory.swift +++ b/Sources/SyndiKit/Common/EntryCategory.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Common/Entryable.swift b/Sources/SyndiKit/Common/Entryable.swift index 71621aff..688a8fb1 100644 --- a/Sources/SyndiKit/Common/Entryable.swift +++ b/Sources/SyndiKit/Common/Entryable.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Common/Feedable.swift b/Sources/SyndiKit/Common/Feedable.swift index a796d5f0..75dd112f 100644 --- a/Sources/SyndiKit/Common/Feedable.swift +++ b/Sources/SyndiKit/Common/Feedable.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Common/Link.swift b/Sources/SyndiKit/Common/Link.swift index 685088a4..7af7033b 100644 --- a/Sources/SyndiKit/Common/Link.swift +++ b/Sources/SyndiKit/Common/Link.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Common/Primitives/CData.swift b/Sources/SyndiKit/Common/Primitives/CData.swift index a0150882..aa569ca2 100644 --- a/Sources/SyndiKit/Common/Primitives/CData.swift +++ b/Sources/SyndiKit/Common/Primitives/CData.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Common/Primitives/ListString.swift b/Sources/SyndiKit/Common/Primitives/ListString.swift index 4e48fdb8..3b1366f5 100644 --- a/Sources/SyndiKit/Common/Primitives/ListString.swift +++ b/Sources/SyndiKit/Common/Primitives/ListString.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Common/Primitives/UTF8EncodedURL.swift b/Sources/SyndiKit/Common/Primitives/UTF8EncodedURL.swift index 8d61bb76..6031559a 100644 --- a/Sources/SyndiKit/Common/Primitives/UTF8EncodedURL.swift +++ b/Sources/SyndiKit/Common/Primitives/UTF8EncodedURL.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Common/Primitives/XMLStringInt.swift b/Sources/SyndiKit/Common/Primitives/XMLStringInt.swift index c059876f..43922144 100644 --- a/Sources/SyndiKit/Common/Primitives/XMLStringInt.swift +++ b/Sources/SyndiKit/Common/Primitives/XMLStringInt.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Decoding/AnyDecoding.swift b/Sources/SyndiKit/Decoding/AnyDecoding.swift index 285d6aa8..0b27b0de 100644 --- a/Sources/SyndiKit/Decoding/AnyDecoding.swift +++ b/Sources/SyndiKit/Decoding/AnyDecoding.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Decoding/CustomDecoderSetup.swift b/Sources/SyndiKit/Decoding/CustomDecoderSetup.swift index 1c66821a..f92d56ad 100644 --- a/Sources/SyndiKit/Decoding/CustomDecoderSetup.swift +++ b/Sources/SyndiKit/Decoding/CustomDecoderSetup.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Decoding/DateFormatterDecoder.swift b/Sources/SyndiKit/Decoding/DateFormatterDecoder.swift index edfdd039..eb586d72 100644 --- a/Sources/SyndiKit/Decoding/DateFormatterDecoder.swift +++ b/Sources/SyndiKit/Decoding/DateFormatterDecoder.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Decoding/DecodableFeed.swift b/Sources/SyndiKit/Decoding/DecodableFeed.swift index 90b9a7c9..d2e70a18 100644 --- a/Sources/SyndiKit/Decoding/DecodableFeed.swift +++ b/Sources/SyndiKit/Decoding/DecodableFeed.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Decoding/DecoderSetup.swift b/Sources/SyndiKit/Decoding/DecoderSetup.swift index fe7c3e64..70acebd8 100644 --- a/Sources/SyndiKit/Decoding/DecoderSetup.swift +++ b/Sources/SyndiKit/Decoding/DecoderSetup.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Decoding/DecoderSource.swift b/Sources/SyndiKit/Decoding/DecoderSource.swift index 0ba654ce..c01445bd 100644 --- a/Sources/SyndiKit/Decoding/DecoderSource.swift +++ b/Sources/SyndiKit/Decoding/DecoderSource.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Decoding/Decoding.swift b/Sources/SyndiKit/Decoding/Decoding.swift index 10d4f916..a366f566 100644 --- a/Sources/SyndiKit/Decoding/Decoding.swift +++ b/Sources/SyndiKit/Decoding/Decoding.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Decoding/DecodingError.swift b/Sources/SyndiKit/Decoding/DecodingError.swift index 65e78720..208a2854 100644 --- a/Sources/SyndiKit/Decoding/DecodingError.swift +++ b/Sources/SyndiKit/Decoding/DecodingError.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Decoding/JSONDecoder.swift b/Sources/SyndiKit/Decoding/JSONDecoder.swift index 1acb3aee..4f714c17 100644 --- a/Sources/SyndiKit/Decoding/JSONDecoder.swift +++ b/Sources/SyndiKit/Decoding/JSONDecoder.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -35,6 +35,9 @@ #if swift(<5.7) @available(macOS 13.0, *) + // Foundation's JSONDecoder predates Sendable on Swift <5.7; + // @unchecked is required for the retroactive conformance there. + // swiftlint:disable:next no_unchecked_sendable extension JSONDecoder: @unchecked Sendable, TypeDecoder {} #else @available(macOS 13.0, *) diff --git a/Sources/SyndiKit/Decoding/SynDecoder+Helpers.swift b/Sources/SyndiKit/Decoding/SynDecoder+Helpers.swift index 1cea88f2..cdd8c46d 100644 --- a/Sources/SyndiKit/Decoding/SynDecoder+Helpers.swift +++ b/Sources/SyndiKit/Decoding/SynDecoder+Helpers.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -94,12 +94,12 @@ extension SynDecoder { ) -> any TypeDecoder { let setup = source as? any CustomDecoderSetup switch (source.source, setup?.setup(decoder:)) { - case let (.xml, .some(setup)): + case (.xml, .some(let setup)): let xml = XMLDecoder() setup(xml) return xml - case let (.json, .some(setup)): + case (.json, .some(let setup)): let json = JSONDecoder() setup(json) return json diff --git a/Sources/SyndiKit/Decoding/SynDecoder.swift b/Sources/SyndiKit/Decoding/SynDecoder.swift index 57c5ccc4..c9b1c18f 100644 --- a/Sources/SyndiKit/Decoding/SynDecoder.swift +++ b/Sources/SyndiKit/Decoding/SynDecoder.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -102,6 +102,7 @@ public final class SynDecoder: Sendable { /// Returns a ``Feedable`` object of the type you specify, decoded from a JSON object. /// - Parameter data: The JSON or XML object to decode. /// - Returns: A ``Feedable`` object + /// - Throws: `DecodingError` if the data is not a valid or decodable feed. /// /// If the data is not valid RSS, this method throws the /// `DecodingError.dataCorrupted(_:)` error. diff --git a/Sources/SyndiKit/Decoding/TypeDecoder.swift b/Sources/SyndiKit/Decoding/TypeDecoder.swift index 629f79b0..c4bcc27d 100644 --- a/Sources/SyndiKit/Decoding/TypeDecoder.swift +++ b/Sources/SyndiKit/Decoding/TypeDecoder.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Decoding/XMLDecoder.swift b/Sources/SyndiKit/Decoding/XMLDecoder.swift index f64e8f78..b08a19e5 100644 --- a/Sources/SyndiKit/Decoding/XMLDecoder.swift +++ b/Sources/SyndiKit/Decoding/XMLDecoder.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Dictionary.swift b/Sources/SyndiKit/Dictionary.swift index 97d8b76a..1a38ba5c 100644 --- a/Sources/SyndiKit/Dictionary.swift +++ b/Sources/SyndiKit/Dictionary.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Blogs/CategoryDescriptor.swift b/Sources/SyndiKit/Formats/Blogs/CategoryDescriptor.swift index c7daaa89..082e057f 100644 --- a/Sources/SyndiKit/Formats/Blogs/CategoryDescriptor.swift +++ b/Sources/SyndiKit/Formats/Blogs/CategoryDescriptor.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Blogs/CategoryLanguage.swift b/Sources/SyndiKit/Formats/Blogs/CategoryLanguage.swift index 505714f6..ec79cf1b 100644 --- a/Sources/SyndiKit/Formats/Blogs/CategoryLanguage.swift +++ b/Sources/SyndiKit/Formats/Blogs/CategoryLanguage.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Blogs/LanguageContentResult.swift b/Sources/SyndiKit/Formats/Blogs/LanguageContentResult.swift index c85b5a1e..cc015a8d 100644 --- a/Sources/SyndiKit/Formats/Blogs/LanguageContentResult.swift +++ b/Sources/SyndiKit/Formats/Blogs/LanguageContentResult.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Blogs/ProcessedBlogsResult.swift b/Sources/SyndiKit/Formats/Blogs/ProcessedBlogsResult.swift index 02058f26..3a6a3105 100644 --- a/Sources/SyndiKit/Formats/Blogs/ProcessedBlogsResult.swift +++ b/Sources/SyndiKit/Formats/Blogs/ProcessedBlogsResult.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -60,7 +60,6 @@ internal struct ProcessedBlogsResult: Sendable { /// A mapping of category types to sets of site indices. internal let categoryIndices: [SiteCategoryType: Set] - // swiftlint:disable function_body_length /// Creates a processed blogs result from a site collection. /// /// - Parameter blogs: The site collection to process. @@ -102,5 +101,4 @@ internal struct ProcessedBlogsResult: Sendable { categoryIndices: categoryIndices ) } - // swiftlint:enable function_body_length } diff --git a/Sources/SyndiKit/Formats/Blogs/Site.swift b/Sources/SyndiKit/Formats/Blogs/Site.swift index 4f3190ce..f90b97b6 100644 --- a/Sources/SyndiKit/Formats/Blogs/Site.swift +++ b/Sources/SyndiKit/Formats/Blogs/Site.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Blogs/SiteCategory.swift b/Sources/SyndiKit/Formats/Blogs/SiteCategory.swift index ffc8a982..91ba24a4 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteCategory.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteCategory.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -55,9 +55,6 @@ public struct SiteCategory: Sendable { /// Initializes a ``SiteCategory`` instance with the given languages. /// /// - Parameter languages: An array of ``CategoryLanguage`` instances. - /// - /// - Returns: A new ``SiteCategory`` instance - /// if at least one language is provided, ``nil`` otherwise. /// - SeeAlso: ``EntryCategory`` internal init?(languages: [CategoryLanguage]) { guard let type = languages.first?.type else { diff --git a/Sources/SyndiKit/Formats/Blogs/SiteCategoryType.swift b/Sources/SyndiKit/Formats/Blogs/SiteCategoryType.swift index a829e074..e3f9e8f4 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteCategoryType.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteCategoryType.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Blogs/SiteCollection.swift b/Sources/SyndiKit/Formats/Blogs/SiteCollection.swift index 1ba987a8..752556fc 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteCollection.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteCollection.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Blogs/SiteCollectionDirectory.swift b/Sources/SyndiKit/Formats/Blogs/SiteCollectionDirectory.swift index ec27569d..7f5a9b30 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteCollectionDirectory.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteCollectionDirectory.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Blogs/SiteCollectionDirectoryBuilder.swift b/Sources/SyndiKit/Formats/Blogs/SiteCollectionDirectoryBuilder.swift new file mode 100644 index 00000000..e4deac23 --- /dev/null +++ b/Sources/SyndiKit/Formats/Blogs/SiteCollectionDirectoryBuilder.swift @@ -0,0 +1,51 @@ +// +// SiteCollectionDirectoryBuilder.swift +// SyndiKit +// +// Created by Leo Dion. +// Copyright © 2026 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#if swift(<6.0) + import Foundation +#else + internal import Foundation +#endif + +/// A builder for creating a site collection directory. +public struct SiteCollectionDirectoryBuilder: SiteDirectoryBuilder, Sendable { + /// Initializes a new instance of ``SiteCollectionDirectoryBuilder``. + public init() {} + + /// A struct representing an Atom category. + /// Creates a site collection directory from a site collection. + /// + /// - Parameter blogs: The site collection to build the directory from. + /// + /// - Returns: A new instance of ``SiteCollectionDirectory``. + /// - SeeAlso: ``EntryCategory`` + public func directory(fromCollection blogs: SiteCollection) -> SiteCollectionDirectory { + SiteCollectionDirectory(blogs: blogs) + } +} diff --git a/Sources/SyndiKit/Formats/Blogs/SiteCollectionProcessor.swift b/Sources/SyndiKit/Formats/Blogs/SiteCollectionProcessor.swift index ce32bff7..ea5fbb72 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteCollectionProcessor.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteCollectionProcessor.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Blogs/SiteDirectory.swift b/Sources/SyndiKit/Formats/Blogs/SiteDirectory.swift index 7efed80c..101b35b2 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteDirectory.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteDirectory.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Blogs/SiteDirectoryBuilder.swift b/Sources/SyndiKit/Formats/Blogs/SiteDirectoryBuilder.swift index 7195eb0b..5557f889 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteDirectoryBuilder.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteDirectoryBuilder.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -33,23 +33,6 @@ internal import Foundation #endif -/// A builder for creating a site collection directory. -public struct SiteCollectionDirectoryBuilder: SiteDirectoryBuilder, Sendable { - /// Initializes a new instance of ``SiteCollectionDirectoryBuilder``. - public init() {} - - /// A struct representing an Atom category. - /// Creates a site collection directory from a site collection. - /// - /// - Parameter blogs: The site collection to build the directory from. - /// - /// - Returns: A new instance of ``SiteCollectionDirectory``. - /// - SeeAlso: ``EntryCategory`` - public func directory(fromCollection blogs: SiteCollection) -> SiteCollectionDirectory { - SiteCollectionDirectory(blogs: blogs) - } -} - /// A protocol for building site directories. public protocol SiteDirectoryBuilder: Sendable { /// The type of site directory to build. diff --git a/Sources/SyndiKit/Formats/Blogs/SiteLanguage.swift b/Sources/SyndiKit/Formats/Blogs/SiteLanguage.swift index f88be38a..4810879f 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteLanguage.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteLanguage.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -51,10 +51,7 @@ public struct SiteLanguage: Sendable { /// A struct representing an Atom category. /// Initializes a new ``SiteLanguage`` instance. /// - /// - Parameters: - /// - content: The content of the site language. - /// - /// - Returns: A new ``SiteLanguage`` instance. + /// - Parameter content: The content of the site language. /// - SeeAlso: ``EntryCategory`` internal init(content: SiteLanguageContent) { type = content.language diff --git a/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory+Site.swift b/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory+Site.swift index f09df746..feef004d 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory+Site.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory+Site.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory.swift b/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory.swift index fea33e89..51c397c2 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteLanguageCategory.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Blogs/SiteLanguageContent.swift b/Sources/SyndiKit/Formats/Blogs/SiteLanguageContent.swift index 3c574743..b6e0cfd0 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteLanguageContent.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteLanguageContent.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Blogs/SiteLanguageType.swift b/Sources/SyndiKit/Formats/Blogs/SiteLanguageType.swift index b1d1f760..a3fcde89 100644 --- a/Sources/SyndiKit/Formats/Blogs/SiteLanguageType.swift +++ b/Sources/SyndiKit/Formats/Blogs/SiteLanguageType.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/Atom/AtomCategory.swift b/Sources/SyndiKit/Formats/Feeds/Atom/AtomCategory.swift index 5f52ec2d..2d091269 100644 --- a/Sources/SyndiKit/Formats/Feeds/Atom/AtomCategory.swift +++ b/Sources/SyndiKit/Formats/Feeds/Atom/AtomCategory.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/Atom/AtomEntry.swift b/Sources/SyndiKit/Formats/Feeds/Atom/AtomEntry.swift index f6f7a8c8..ced8b2d7 100644 --- a/Sources/SyndiKit/Formats/Feeds/Atom/AtomEntry.swift +++ b/Sources/SyndiKit/Formats/Feeds/Atom/AtomEntry.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/Atom/AtomFeed.swift b/Sources/SyndiKit/Formats/Feeds/Atom/AtomFeed.swift index e3d61784..fdb09bad 100644 --- a/Sources/SyndiKit/Formats/Feeds/Atom/AtomFeed.swift +++ b/Sources/SyndiKit/Formats/Feeds/Atom/AtomFeed.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/Atom/AtomMedia.swift b/Sources/SyndiKit/Formats/Feeds/Atom/AtomMedia.swift index d5740f31..02f12fe6 100644 --- a/Sources/SyndiKit/Formats/Feeds/Atom/AtomMedia.swift +++ b/Sources/SyndiKit/Formats/Feeds/Atom/AtomMedia.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/Atom/AtomMediaGroup.swift b/Sources/SyndiKit/Formats/Feeds/Atom/AtomMediaGroup.swift index ee72fd8a..4fa6690f 100644 --- a/Sources/SyndiKit/Formats/Feeds/Atom/AtomMediaGroup.swift +++ b/Sources/SyndiKit/Formats/Feeds/Atom/AtomMediaGroup.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/JSONFeed/JSONFeed.swift b/Sources/SyndiKit/Formats/Feeds/JSONFeed/JSONFeed.swift index 88cedf50..3a7d7205 100644 --- a/Sources/SyndiKit/Formats/Feeds/JSONFeed/JSONFeed.swift +++ b/Sources/SyndiKit/Formats/Feeds/JSONFeed/JSONFeed.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/JSONFeed/JSONItem.swift b/Sources/SyndiKit/Formats/Feeds/JSONFeed/JSONItem.swift index c30f65c9..55bbe2b1 100644 --- a/Sources/SyndiKit/Formats/Feeds/JSONFeed/JSONItem.swift +++ b/Sources/SyndiKit/Formats/Feeds/JSONFeed/JSONItem.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/Enclosure.swift b/Sources/SyndiKit/Formats/Feeds/RSS/Enclosure.swift index b7d880b1..ca8588c6 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/Enclosure.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/Enclosure.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/EntryID.swift b/Sources/SyndiKit/Formats/Feeds/RSS/EntryID.swift index ec2d7090..241ee886 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/EntryID.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/EntryID.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -61,16 +61,16 @@ public enum EntryID: Codable, Equatable, LosslessStringConvertible, Sendable { public var description: String { let string: String switch self { - case let .url(url): + case .url(let url): string = url.absoluteString - case let .uuid(uuid): + case .uuid(let uuid): string = uuid.uuidString.lowercased() - case let .path(components, separatedBy: separator): + case .path(let components, separatedBy: let separator): string = components.joined(separator: separator) - case let .string(value): + case .string(let value): string = value } return string diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/Properties/BasicProperties.swift b/Sources/SyndiKit/Formats/Feeds/RSS/Properties/BasicProperties.swift index d225aa59..799b5175 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/Properties/BasicProperties.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/Properties/BasicProperties.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/Properties/ITunesProperties.swift b/Sources/SyndiKit/Formats/Feeds/RSS/Properties/ITunesProperties.swift index 2f8683df..86dd64c0 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/Properties/ITunesProperties.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/Properties/ITunesProperties.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/Properties/MediaProperties.swift b/Sources/SyndiKit/Formats/Feeds/RSS/Properties/MediaProperties.swift index 9bf6657d..396da3af 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/Properties/MediaProperties.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/Properties/MediaProperties.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/Properties/PodcastProperties.swift b/Sources/SyndiKit/Formats/Feeds/RSS/Properties/PodcastProperties.swift index 4f7aa325..6c8c4051 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/Properties/PodcastProperties.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/Properties/PodcastProperties.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/Properties/WordPressProperties.swift b/Sources/SyndiKit/Formats/Feeds/RSS/Properties/WordPressProperties.swift index 0a7b487b..a44f9e64 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/Properties/WordPressProperties.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/Properties/WordPressProperties.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/RSSChannel.swift b/Sources/SyndiKit/Formats/Feeds/RSS/RSSChannel.swift index c08be09c..7d368078 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/RSSChannel.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/RSSChannel.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -70,6 +70,8 @@ public struct RSSChannel: Codable, Sendable { case image case author case managingEditor + // RSS 2.0 spec element name ; public API, cannot rename. + // swiftlint:disable:next inclusive_language case webMaster case wpCategories = "wp:category" case wpTags = "wp:tag" @@ -139,6 +141,8 @@ public struct RSSChannel: Codable, Sendable { /// - SeeAlso: ``Author`` public let managingEditor: Author? + // RSS 2.0 spec element name ; public API, cannot rename. + // swiftlint:disable inclusive_language /// Email address and name for the person responsible for technical issues. /// /// Parses RFC 822 format like `webmaster@example.com (John Smith)` or @@ -149,6 +153,7 @@ public struct RSSChannel: Codable, Sendable { /// /// - SeeAlso: ``Author`` public let webMaster: Author? + // swiftlint:enable inclusive_language /// The categories associated with the channel. public let wpCategories: [WordPressElements.Category] diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/RSSFeed.swift b/Sources/SyndiKit/Formats/Feeds/RSS/RSSFeed.swift index f9339d1c..08ec9dc7 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/RSSFeed.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/RSSFeed.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/RSSImage.swift b/Sources/SyndiKit/Formats/Feeds/RSS/RSSImage.swift index 7a91cc5b..37ef3901 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/RSSImage.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/RSSImage.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+Init.swift b/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+Init.swift index ad70a91b..94c434da 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+Init.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+Init.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+InternalInit.swift b/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+InternalInit.swift index e7e26e23..a42c6c69 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+InternalInit.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem+InternalInit.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -38,7 +38,6 @@ import XMLCoder #endif extension RSSItem { - // swiftlint:disable function_body_length /// Initializes a new ``RSSItem`` instance with property sets. /// /// - Parameters: @@ -121,5 +120,4 @@ extension RSSItem { self.mediaContent = mediaContent self.mediaThumbnail = mediaThumbnail } - // swiftlint:enable function_body_length } diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem.swift b/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem.swift index 15e6cafe..2e3ef5c0 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/RSSItem.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Feeds/RSS/RSSItemCategory.swift b/Sources/SyndiKit/Formats/Feeds/RSS/RSSItemCategory.swift index 1db1a184..d8e2b114 100644 --- a/Sources/SyndiKit/Formats/Feeds/RSS/RSSItemCategory.swift +++ b/Sources/SyndiKit/Formats/Feeds/RSS/RSSItemCategory.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -71,8 +71,6 @@ public struct RSSItemCategory: Codable, EntryCategory, Sendable { /// - value: The value of the category. /// - domain: The domain of the category. Default value is ``nil``. /// - nicename: The nicename of the category. Default value is ``nil``. - /// - /// - Returns: A new instance of ``RSSItemCategory``. /// - SeeAlso: ``EntryCategory`` public init(value: String, domain: String? = nil, nicename: String? = nil) { self.value = value @@ -86,8 +84,6 @@ public struct RSSItemCategory: Codable, EntryCategory, Sendable { /// - Parameter decoder: The decoder to use for decoding. /// /// - Throws: An error if the decoding fails. - /// - /// - Returns: A new instance of ``RSSItemCategory``. /// - SeeAlso: ``EntryCategory`` public init(from decoder: any Decoder) throws { let value: String diff --git a/Sources/SyndiKit/Formats/Media/MediaContent.swift b/Sources/SyndiKit/Formats/Media/MediaContent.swift index 69634acc..925284e8 100644 --- a/Sources/SyndiKit/Formats/Media/MediaContent.swift +++ b/Sources/SyndiKit/Formats/Media/MediaContent.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters+MimeType.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters+MimeType.swift index e6f8bc7f..8203984d 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters+MimeType.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters+MimeType.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -64,7 +64,7 @@ extension PodcastChapters { public var rawValue: String { if let knownMimeType = KnownMimeType(mimeType: self) { return knownMimeType.rawValue - } else if case let .unknown(string) = self { + } else if case .unknown(let string) = self { return string } else { fatalError( diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters.swift index af72a246..8bb782f0 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastChapters.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisode.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisode.swift index 4c07ba09..19dc6668 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisode.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisode.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -33,63 +33,6 @@ public import Foundation #endif -/// A struct representing properties of a podcast episode. -internal struct PodcastEpisodeProperties: PodcastEpisode, Sendable { - /// The title of the episode. - internal let title: String? - - /// The episode number. - internal let episode: Int? - - /// The author of the episode. - internal let author: String? - - /// The subtitle of the episode. - internal let subtitle: String? - - /// A summary of the episode. - internal let summary: String? - - /// Indicates if the episode contains explicit content. - internal let explicit: String? - - /// The duration of the episode. - internal let duration: TimeInterval? - - /// The image associated with the episode. - internal let image: iTunesImage? - - /// The enclosure of the episode. - internal let enclosure: Enclosure - - /// The people involved in the episode. - internal let people: [PodcastPerson] - - /// A struct representing an Atom category. - /// Initializes a ``PodcastEpisodeProperties`` instance from an ``RSSItem``. - /// - /// - Parameter rssItem: The ``RSSItem`` to extract the properties from. - /// - /// - Returns: An initialized ``PodcastEpisodeProperties`` instance, - /// or ``nil`` if the ``enclosure`` property is missing. - /// - SeeAlso: ``EntryCategory`` - internal init?(rssItem: RSSItem) { - guard let enclosure = rssItem.enclosure else { - return nil - } - title = rssItem.itunesTitle - episode = rssItem.itunesEpisode?.value - author = rssItem.itunesAuthor - subtitle = rssItem.itunesSubtitle - summary = rssItem.itunesSummary?.value - explicit = rssItem.itunesExplicit - duration = rssItem.itunesDuration?.value - image = rssItem.itunesImage - self.enclosure = enclosure - people = rssItem.podcastPeople - } -} - /// A protocol representing a podcast episode. public protocol PodcastEpisode: Sendable { /// The title of the episode. diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisodeProperties.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisodeProperties.swift new file mode 100644 index 00000000..b19a8806 --- /dev/null +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastEpisodeProperties.swift @@ -0,0 +1,88 @@ +// +// PodcastEpisodeProperties.swift +// SyndiKit +// +// Created by Leo Dion. +// Copyright © 2026 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#if swift(<6.0) + import Foundation +#else + internal import Foundation +#endif + +/// A struct representing properties of a podcast episode. +internal struct PodcastEpisodeProperties: PodcastEpisode, Sendable { + /// The title of the episode. + internal let title: String? + + /// The episode number. + internal let episode: Int? + + /// The author of the episode. + internal let author: String? + + /// The subtitle of the episode. + internal let subtitle: String? + + /// A summary of the episode. + internal let summary: String? + + /// Indicates if the episode contains explicit content. + internal let explicit: String? + + /// The duration of the episode. + internal let duration: TimeInterval? + + /// The image associated with the episode. + internal let image: iTunesImage? + + /// The enclosure of the episode. + internal let enclosure: Enclosure + + /// The people involved in the episode. + internal let people: [PodcastPerson] + + /// A struct representing an Atom category. + /// Initializes a ``PodcastEpisodeProperties`` instance from an ``RSSItem``. + /// + /// - Parameter rssItem: The ``RSSItem`` to extract the properties from. + /// - SeeAlso: ``EntryCategory`` + internal init?(rssItem: RSSItem) { + guard let enclosure = rssItem.enclosure else { + return nil + } + title = rssItem.itunesTitle + episode = rssItem.itunesEpisode?.value + author = rssItem.itunesAuthor + subtitle = rssItem.itunesSubtitle + summary = rssItem.itunesSummary?.value + explicit = rssItem.itunesExplicit + duration = rssItem.itunesDuration?.value + image = rssItem.itunesImage + self.enclosure = enclosure + people = rssItem.podcastPeople + } +} diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastFunding.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastFunding.swift index 693b8aa4..623b0d8e 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastFunding.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastFunding.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+GeoURI.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+GeoURI.swift index aec037ed..c24cd627 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+GeoURI.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+GeoURI.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+OsmQuery.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+OsmQuery.swift index 8cae9287..4640aeae 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+OsmQuery.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation+OsmQuery.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation.swift index 6ae05c18..1c3dddea 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocation.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocked.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocked.swift index 8f02bc8b..b5517d2d 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocked.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastLocked.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson+Role.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson+Role.swift index 68f753cc..bfa33aae 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson+Role.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson+Role.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -96,7 +96,7 @@ extension PodcastPerson { public var rawValue: String { if let knownRole = KnownRole(role: self) { return knownRole.rawValue - } else if case let .unknown(string) = self { + } else if case .unknown(let string) = self { return string } else { fatalError( diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson.swift index dfc51d3e..32d57d46 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastPerson.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastSeason.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastSeason.swift index 5efe6102..b3c843ab 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastSeason.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastSeason.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastSoundbite.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastSoundbite.swift index af3da562..29e100af 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastSoundbite.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastSoundbite.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript+MimeType.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript+MimeType.swift index badda215..87cf39fc 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript+MimeType.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript+MimeType.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -78,7 +78,7 @@ extension PodcastTranscript { public var rawValue: String { if let knownMimeType = KnownMimeType(mimeType: self) { return knownMimeType.rawValue - } else if case let .unknown(string) = self { + } else if case .unknown(let string) = self { return string } else { fatalError( diff --git a/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript.swift b/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript.swift index def8c6fe..e26fc3e2 100644 --- a/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript.swift +++ b/Sources/SyndiKit/Formats/Media/Podcast/PodcastTranscript.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Video.swift b/Sources/SyndiKit/Formats/Media/Video.swift index 0b83fb6e..560f7afd 100644 --- a/Sources/SyndiKit/Formats/Media/Video.swift +++ b/Sources/SyndiKit/Formats/Media/Video.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/Entryable+WordPressPost.swift b/Sources/SyndiKit/Formats/Media/Wordpress/Entryable+WordPressPost.swift index 50d7fac1..8e45fde5 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/Entryable+WordPressPost.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/Entryable+WordPressPost.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WPCategory.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WPCategory.swift index 00b9fdb4..a66eadef 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WPCategory.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WPCategory.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WPPostMeta.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WPPostMeta.swift index 334231cd..fd156896 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WPPostMeta.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WPPostMeta.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WPTag.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WPTag.swift index a7b73adc..9aae251a 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WPTag.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WPTag.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressElements.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressElements.swift index 06633451..3f236ce2 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressElements.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressElements.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressError.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressError.swift index d987fbc5..67ac3ebf 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressError.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressError.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+BasicProperties.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+BasicProperties.swift index 362929f1..0e8608e2 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+BasicProperties.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+BasicProperties.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+CategoryProperties.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+CategoryProperties.swift index 56ecce8f..f3a99ed8 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+CategoryProperties.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+CategoryProperties.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+DateProperties.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+DateProperties.swift index 3ab4b9ee..fcd85e40 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+DateProperties.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+DateProperties.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Hashable.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Hashable.swift index bf808635..bf6f69b3 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Hashable.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Hashable.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Init.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Init.swift index 783284f3..b90a4ba5 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Init.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Init.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+MetaProperties.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+MetaProperties.swift index 62d5f95c..690dd2fa 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+MetaProperties.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+MetaProperties.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+ProcessedData.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+ProcessedData.swift index db3c45a2..4b4632d2 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+ProcessedData.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+ProcessedData.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+ProcessedFields.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+ProcessedFields.swift index c25e6d3c..9cd0f889 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+ProcessedFields.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+ProcessedFields.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Processor.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Processor.swift index 9fb9e716..3cda3fe9 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Processor.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Processor.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+ValidatedFields.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+ValidatedFields.swift index 54865ed1..c87893a4 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+ValidatedFields.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+ValidatedFields.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -118,7 +118,6 @@ extension WordPressPost { self.title = title } - // swiftlint:disable function_body_length /// Initializes a ValidatedFields instance /// by validating all required fields from an RSSItem. /// @@ -158,6 +157,5 @@ extension WordPressPost { title: item.title ) } - // swiftlint:enable function_body_length } } diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Validator.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Validator.swift index afd4e13c..2af73613 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Validator.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost+Validator.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost.swift b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost.swift index f2b0818e..2af7fd14 100644 --- a/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost.swift +++ b/Sources/SyndiKit/Formats/Media/Wordpress/WordPressPost.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/Media/YouTube/YouTubeID.swift b/Sources/SyndiKit/Formats/Media/YouTube/YouTubeID.swift index 68775041..84bdcf46 100644 --- a/Sources/SyndiKit/Formats/Media/YouTube/YouTubeID.swift +++ b/Sources/SyndiKit/Formats/Media/YouTube/YouTubeID.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -33,44 +33,6 @@ internal import Foundation #endif -/// A struct representing an Atom category. -/// A struct representing the properties of a YouTube ID. -/// -/// - Note: This struct conforms to the ``YouTubeID`` protocol. -/// -/// - SeeAlso: ``YouTubeID`` -/// -/// - Important: This struct is internal. -/// -/// - Parameters: -/// - videoID: The YouTube video ID. -/// - channelID: The YouTube channel ID. -/// - SeeAlso: ``EntryCategory`` -internal struct YouTubeIDProperties: YouTubeID, Sendable { - internal let videoID: String - internal let channelID: String - - /// A struct representing an Atom category. - /// Initializes a ``YouTubeIDProperties`` instance with the given AtomEntry. - /// - /// - Parameters: - /// - entry: The AtomEntry containing the YouTube ID properties. - /// - /// - Returns: A new ``YouTubeIDProperties`` instance, - /// or ``nil`` if the required properties are missing. - /// - SeeAlso: ``EntryCategory`` - internal init?(entry: AtomEntry) { - guard - let channelID = entry.youtubeChannelID, - let videoID = entry.youtubeVideoID - else { - return nil - } - self.channelID = channelID - self.videoID = videoID - } -} - /// A struct representing an Atom category. /// A protocol abstracting the ID properties of a YouTube RSS Feed. /// diff --git a/Sources/SyndiKit/Formats/Media/YouTube/YouTubeIDProperties.swift b/Sources/SyndiKit/Formats/Media/YouTube/YouTubeIDProperties.swift new file mode 100644 index 00000000..1a1157f9 --- /dev/null +++ b/Sources/SyndiKit/Formats/Media/YouTube/YouTubeIDProperties.swift @@ -0,0 +1,68 @@ +// +// YouTubeIDProperties.swift +// SyndiKit +// +// Created by Leo Dion. +// Copyright © 2026 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +#if swift(<6.0) + import Foundation +#else + internal import Foundation +#endif + +/// A struct representing an Atom category. +/// A struct representing the properties of a YouTube ID. +/// +/// - Note: This struct conforms to the ``YouTubeID`` protocol. +/// +/// - SeeAlso: ``YouTubeID`` +/// +/// - Important: This struct is internal. +/// +/// - Parameters: +/// - videoID: The YouTube video ID. +/// - channelID: The YouTube channel ID. +/// - SeeAlso: ``EntryCategory`` +internal struct YouTubeIDProperties: YouTubeID, Sendable { + internal let videoID: String + internal let channelID: String + + /// A struct representing an Atom category. + /// Initializes a ``YouTubeIDProperties`` instance with the given AtomEntry. + /// + /// - Parameter entry: The AtomEntry containing the YouTube ID properties. + /// - SeeAlso: ``EntryCategory`` + internal init?(entry: AtomEntry) { + guard + let channelID = entry.youtubeChannelID, + let videoID = entry.youtubeVideoID + else { + return nil + } + self.channelID = channelID + self.videoID = videoID + } +} diff --git a/Sources/SyndiKit/Formats/Media/iTunes/iTunesDuration.swift b/Sources/SyndiKit/Formats/Media/iTunes/iTunesDuration.swift index d42ab430..14e16039 100644 --- a/Sources/SyndiKit/Formats/Media/iTunes/iTunesDuration.swift +++ b/Sources/SyndiKit/Formats/Media/iTunes/iTunesDuration.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -33,6 +33,8 @@ public import Foundation #endif +// Intentional Apple iTunes branding; lowercase "i" prefix is required. +// swiftlint:disable type_name // swift-format-ignore: TypeNamesShouldBeCapitalized /// A struct representing the duration of an iTunes track. public struct iTunesDuration: Codable, ExpressibleByFloatLiteral, Sendable { @@ -71,7 +73,6 @@ public struct iTunesDuration: Codable, ExpressibleByFloatLiteral, Sendable { /// Creates a new instance from the given description string. /// /// - Parameter description: The description string representing the duration. - /// - Returns: A new instance if the description is valid, otherwise ``nil``. public init?(_ description: String) { guard let value = Self.timeInterval(description) else { return nil @@ -95,3 +96,4 @@ public struct iTunesDuration: Codable, ExpressibleByFloatLiteral, Sendable { } } } +// swiftlint:enable type_name diff --git a/Sources/SyndiKit/Formats/Media/iTunes/iTunesEpisode.swift b/Sources/SyndiKit/Formats/Media/iTunes/iTunesEpisode.swift index 5f05df3f..39079c39 100644 --- a/Sources/SyndiKit/Formats/Media/iTunes/iTunesEpisode.swift +++ b/Sources/SyndiKit/Formats/Media/iTunes/iTunesEpisode.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -33,6 +33,8 @@ internal import Foundation #endif +// Intentional Apple iTunes branding; lowercase "i" prefix is required. +// swiftlint:disable type_name // swift-format-ignore: TypeNamesShouldBeCapitalized /// A struct representing an Atom category. /// A type alias for an iTunes episode. @@ -42,3 +44,4 @@ /// - SeeAlso: ``XMLStringInt`` /// - SeeAlso: ``EntryCategory`` public typealias iTunesEpisode = XMLStringInt +// swiftlint:enable type_name diff --git a/Sources/SyndiKit/Formats/Media/iTunes/iTunesImage.swift b/Sources/SyndiKit/Formats/Media/iTunes/iTunesImage.swift index 3ef77dc0..ae8a87a3 100644 --- a/Sources/SyndiKit/Formats/Media/iTunes/iTunesImage.swift +++ b/Sources/SyndiKit/Formats/Media/iTunes/iTunesImage.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -33,6 +33,9 @@ internal import Foundation #endif +// Intentional Apple iTunes branding; lowercase "i" prefix is required. +// swiftlint:disable type_name // swift-format-ignore: TypeNamesShouldBeCapitalized /// A type alias for iTunes image links. public typealias iTunesImage = Link +// swiftlint:enable type_name diff --git a/Sources/SyndiKit/Formats/Media/iTunes/iTunesOwner.swift b/Sources/SyndiKit/Formats/Media/iTunes/iTunesOwner.swift index a02cacd9..932e1a9b 100644 --- a/Sources/SyndiKit/Formats/Media/iTunes/iTunesOwner.swift +++ b/Sources/SyndiKit/Formats/Media/iTunes/iTunesOwner.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT @@ -35,6 +35,8 @@ internal import Foundation #endif +// Intentional Apple iTunes branding; lowercase "i" prefix is required. +// swiftlint:disable type_name // swift-format-ignore: TypeNamesShouldBeCapitalized /// A struct representing an Atom category. /// A struct representing the owner of an iTunes account. @@ -64,3 +66,4 @@ public struct iTunesOwner: Codable, Sendable { /// The email address of the iTunes owner. public let email: String? } +// swiftlint:enable type_name diff --git a/Sources/SyndiKit/Formats/OPML/OPML+Body.swift b/Sources/SyndiKit/Formats/OPML/OPML+Body.swift index fdfeaeb5..ee18c624 100644 --- a/Sources/SyndiKit/Formats/OPML/OPML+Body.swift +++ b/Sources/SyndiKit/Formats/OPML/OPML+Body.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/OPML/OPML+Head.swift b/Sources/SyndiKit/Formats/OPML/OPML+Head.swift index 0c5e7c6a..eb663b7b 100644 --- a/Sources/SyndiKit/Formats/OPML/OPML+Head.swift +++ b/Sources/SyndiKit/Formats/OPML/OPML+Head.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/OPML/OPML+Outline.swift b/Sources/SyndiKit/Formats/OPML/OPML+Outline.swift index cdcf2f81..4c45613f 100644 --- a/Sources/SyndiKit/Formats/OPML/OPML+Outline.swift +++ b/Sources/SyndiKit/Formats/OPML/OPML+Outline.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/OPML/OPML.swift b/Sources/SyndiKit/Formats/OPML/OPML.swift index 73862840..35ed72be 100644 --- a/Sources/SyndiKit/Formats/OPML/OPML.swift +++ b/Sources/SyndiKit/Formats/OPML/OPML.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/OPML/OutlineType.swift b/Sources/SyndiKit/Formats/OPML/OutlineType.swift index 4a75fdba..74d21563 100644 --- a/Sources/SyndiKit/Formats/OPML/OutlineType.swift +++ b/Sources/SyndiKit/Formats/OPML/OutlineType.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/SyndicationUpdate/SyndicationUpdate.swift b/Sources/SyndiKit/Formats/SyndicationUpdate/SyndicationUpdate.swift index 32e7cd71..964eb1ef 100644 --- a/Sources/SyndiKit/Formats/SyndicationUpdate/SyndicationUpdate.swift +++ b/Sources/SyndiKit/Formats/SyndicationUpdate/SyndicationUpdate.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/SyndicationUpdate/SyndicationUpdateFrequency.swift b/Sources/SyndiKit/Formats/SyndicationUpdate/SyndicationUpdateFrequency.swift index 0d296660..19e09ede 100644 --- a/Sources/SyndiKit/Formats/SyndicationUpdate/SyndicationUpdateFrequency.swift +++ b/Sources/SyndiKit/Formats/SyndicationUpdate/SyndicationUpdateFrequency.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/Formats/SyndicationUpdate/SyndicationUpdatePeriod.swift b/Sources/SyndiKit/Formats/SyndicationUpdate/SyndicationUpdatePeriod.swift index a1f5f98f..6316d825 100644 --- a/Sources/SyndiKit/Formats/SyndicationUpdate/SyndicationUpdatePeriod.swift +++ b/Sources/SyndiKit/Formats/SyndicationUpdate/SyndicationUpdatePeriod.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/KeyedDecodingContainerProtocol.swift b/Sources/SyndiKit/KeyedDecodingContainerProtocol.swift index eaf19102..e26f331a 100644 --- a/Sources/SyndiKit/KeyedDecodingContainerProtocol.swift +++ b/Sources/SyndiKit/KeyedDecodingContainerProtocol.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/StringProtocol.swift b/Sources/SyndiKit/StringProtocol.swift index f36d8e06..5016316b 100644 --- a/Sources/SyndiKit/StringProtocol.swift +++ b/Sources/SyndiKit/StringProtocol.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Sources/SyndiKit/SyndiKit.docc/SyndiKit.md b/Sources/SyndiKit/SyndiKit.docc/SyndiKit.md index 8db52296..85fffa1c 100644 --- a/Sources/SyndiKit/SyndiKit.docc/SyndiKit.md +++ b/Sources/SyndiKit/SyndiKit.docc/SyndiKit.md @@ -12,7 +12,7 @@ Built on top of [XMLCoder](https://github.com/CoreOffice/XMLCoder), **SyndiKit** * Import of RSS 2.0, Atom, and JSONFeed formats * Extensions for various formats such as: - * iTunes-compatabile podcasts + * iTunes-compatible podcasts * YouTube channels * WordPress export data * User-friendly errors @@ -22,18 +22,18 @@ Built on top of [XMLCoder](https://github.com/CoreOffice/XMLCoder), **SyndiKit** **Apple Platforms** -- Xcode 13.3 or later -- Swift 5.5.2 or later -- iOS 15.4 / watchOS 8.5 / tvOS 15.4 / macOS 12.3 or later deployment targets +- Xcode 15.3 or later +- Swift 5.10 or later +- iOS 13 / watchOS 6 / tvOS 13 / macOS 10.15 or later deployment targets **Linux** -- Ubuntu 18.04 or later -- Swift 5.5.2 or later +- Ubuntu 20.04 or later +- Swift 5.10 or later ### Installation -Swift Package Manager is Apple's decentralized dependency manager to integrate libraries to your Swift projects. It is now fully integrated with Xcode 11. +Swift Package Manager is Apple's decentralized dependency manager to integrate libraries to your Swift projects. It is now fully integrated with Xcode. To integrate **SyndiKit** into your project using SPM, specify it in your Package.swift file: @@ -41,7 +41,7 @@ To integrate **SyndiKit** into your project using SPM, specify it in your Packag let package = Package( ... dependencies: [ - .package(url: "https://github.com/brightdigit/SyndiKit", from: "0.3.0") + .package(url: "https://github.com/brightdigit/SyndiKit", from: "1.0.0") ], targets: [ .target( @@ -64,7 +64,7 @@ You can get started decoding your feed by creating your first ``SynDecoder``. On ```swift let decoder = SynDecoder() -let empowerAppsData = Data(contentsOf: "empowerapps-show.xml")! +let empowerAppsData = try Data(contentsOf: URL(fileURLWithPath: "empowerapps-show.xml")) let empowerAppsRSSFeed = try decoder.decode(empowerAppsData) ``` @@ -76,12 +76,12 @@ Rather than working directly with the various formats, **SyndiKit** abstracts ma let decoder = SynDecoder() // decoding a RSS 2.0 feed -let empowerAppsData = Data(contentsOf: "empowerapps-show.xml")! +let empowerAppsData = try Data(contentsOf: URL(fileURLWithPath: "empowerapps-show.xml")) let empowerAppsRSSFeed = try decoder.decode(empowerAppsData) print(empowerAppsRSSFeed.title) // Prints "Empower Apps" // decoding a Atom feed from YouTube -let kiloLocoData = Data(contentsOf: "kilo.youtube.xml")! +let kiloLocoData = try Data(contentsOf: URL(fileURLWithPath: "kilo.youtube.xml")) let kiloLocoAtomFeed = try decoder.decode(kiloLocoData) print(kiloLocoAtomFeed.title) // Prints "Kilo Loco" ``` @@ -91,8 +91,8 @@ For a mapping of properties: Feedable | RSS 2.0 ``RSSFeed/channel`` | Atom ``AtomFeed`` | JSONFeed ``JSONFeed`` --- | --- | --- | --- ``Feedable/title`` | ``RSSChannel/title`` | ``AtomFeed/title`` | ``JSONFeed/title`` -``Feedable/siteURL`` | ``RSSChannel/link`` | ``AtomFeed/siteURL``| ``JSONFeed/title`` -``Feedable/summary`` | ``RSSChannel/description`` | ``AtomFeed/summary`` | ``JSONFeed/homePageUrl`` +``Feedable/siteURL`` | ``RSSChannel/link`` | ``AtomFeed/siteURL``| ``JSONFeed/homePageUrl`` +``Feedable/summary`` | ``RSSChannel/description`` | ``AtomFeed/summary`` | ``JSONFeed/description`` ``Feedable/updated`` | ``RSSChannel/lastBuildDate`` | ``AtomFeed/pubDate`` or ``AtomFeed/published`` | `nil` ``Feedable/authors`` | ``RSSChannel/author`` | ``AtomFeed/authors`` | ``JSONFeed/author`` ``Feedable/copyright`` | ``RSSChannel/copyright`` | `nil` | `nil` @@ -132,7 +132,7 @@ switch empowerAppsRSSFeed.children.last?.media { let kiloLocoAtomFeed = try decoder.decode(kiloLocoData) switch kiloLocoAtomFeed.children.last?.media { - case .video(.youtube(let youtube): + case .video(.youtube(let youtube)): print(youtube.videoID) // print "SBJFl-3wqx8" print(youtube.channelID) // print "UCv75sKQFFIenWHrprnrR9aA" default: @@ -156,7 +156,7 @@ switch kiloLocoAtomFeed.children.last?.media { ### License -This code is distributed under the MIT license. See the [LICENSE](https://github.com/brightdigit/SyndiKit/LICENSE) file for more info. +This code is distributed under the MIT license. See the [LICENSE](https://github.com/brightdigit/SyndiKit/blob/main/LICENSE) file for more info. ## Topics @@ -216,7 +216,7 @@ Specific properties related to the JSON Feed format. - ``JSONFeed`` - ``JSONItem`` -### OPML Feed Formate +### OPML Feed Format - ``OPML`` - ``OutlineType`` diff --git a/Sources/SyndiKit/URL.swift b/Sources/SyndiKit/URL.swift index 08a7907b..cda79dc1 100644 --- a/Sources/SyndiKit/URL.swift +++ b/Sources/SyndiKit/URL.swift @@ -7,7 +7,7 @@ // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation -// files (the “Software”), to deal in the Software without +// files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the @@ -17,7 +17,7 @@ // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // -// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT diff --git a/Tests/SyndiKitTestSupport/Content.Directories.swift b/Tests/SyndiKitTestSupport/Content.Directories.swift index 111aea17..0d549bfd 100644 --- a/Tests/SyndiKitTestSupport/Content.Directories.swift +++ b/Tests/SyndiKitTestSupport/Content.Directories.swift @@ -1,14 +1,14 @@ #if swift(<6.0) - import SyndiKit import Foundation + import SyndiKit #else - internal import SyndiKit internal import Foundation + internal import SyndiKit #endif extension Content { internal enum Directories { - static let data: URL = { + internal static let data: URL = { // Strategy 1: Working directory relative (most reliable for SPM/WASM/Android) // Try this FIRST because it works on WASM when tests run from package root let workingDirPath = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) @@ -44,9 +44,9 @@ extension Content { return workingDirPath }() - static let xml = data.appendingPathComponent("XML") - static let json = data.appendingPathComponent("JSON") - static let opml = data.appendingPathComponent("OPML") - static let wordPress = data.appendingPathComponent("WordPress") + internal static let xml = data.appendingPathComponent("XML") + internal static let json = data.appendingPathComponent("JSON") + internal static let opml = data.appendingPathComponent("OPML") + internal static let wordPress = data.appendingPathComponent("WordPress") } } diff --git a/Tests/SyndiKitTestSupport/Content.ResultDictionary.swift b/Tests/SyndiKitTestSupport/Content.ResultDictionary.swift index 98002088..5b64cb8d 100644 --- a/Tests/SyndiKitTestSupport/Content.ResultDictionary.swift +++ b/Tests/SyndiKitTestSupport/Content.ResultDictionary.swift @@ -1,63 +1,78 @@ import XMLCoder #if swift(<6.0) - import SyndiKit import Foundation + import SyndiKit #else - internal import SyndiKit internal import Foundation + internal import SyndiKit #endif -enum Content { - typealias ResultDictionary = [String: Result] - - fileprivate static func resultDictionaryFrom( - directoryURL: URL, - by closure: @escaping (Data) throws -> SuccessValueType - ) throws -> ResultDictionary { - let xmlDataSet = Result { - try FileManager.default.dataFromDirectory(at: directoryURL) - } - - return try xmlDataSet.map { xmlDataSet in - xmlDataSet.flatResultMapValue(closure) - }.map(Dictionary.init(uniqueKeysWithValues:)).get() - } +internal enum Content { + internal typealias ResultDictionary = [String: Result] @available(macOS 13.0, *) - static let synDecoder = SynDecoder() - static var xmlDecoder: XMLCoder.XMLDecoder { + internal static let synDecoder = SynDecoder() + internal static var xmlDecoder: XMLCoder.XMLDecoder { XMLCoder.XMLDecoder() } #if !os(WASI) // macOS/Linux: Load all feeds eagerly (faster, more memory available) + // swift-format-ignore: NeverUseForceTry @available(macOS 13.0, *) - static let xmlFeeds = try! Content.resultDictionaryFrom( + // swiftlint:disable:next force_try + internal static let xmlFeeds = try! Content.resultDictionaryFrom( directoryURL: Directories.xml, by: Self.synDecoder.decode(_:) ) + // swift-format-ignore: NeverUseForceTry @available(macOS 13.0, *) - static let jsonFeeds = try! Content.resultDictionaryFrom( + // swiftlint:disable:next force_try + internal static let jsonFeeds = try! Content.resultDictionaryFrom( directoryURL: Directories.json, by: Self.synDecoder.decode(_:) ) - static let wordpressDataSet = try! FileManager.default.dataFromDirectory( + // swift-format-ignore: NeverUseForceTry + // swiftlint:disable:next force_try + internal static let wordpressDataSet = try! FileManager.default.dataFromDirectory( at: Directories.wordPress ) #endif // WASM: Only OPML tests run (uses explicit file list in FileManager.dataFromDirectory) // All other test data (xmlFeeds, jsonFeeds, wordpressDataSet) is disabled above due to memory constraints - static let opml = try! Content.resultDictionaryFrom( + // swift-format-ignore: NeverUseForceTry + // swiftlint:disable:next force_try + internal static let opml = try! Content.resultDictionaryFrom( directoryURL: Directories.opml, by: Self.xmlDecoder.decodeOPML(_:) ) - static let blogs: SiteCollection = try! .init( - contentsOf: Directories.data.appendingPathComponent("blogs.json")) + // swift-format-ignore: NeverUseForceTry + // swiftlint:disable:next force_try + internal static let blogs: SiteCollection = try! .init( + contentsOf: Directories.data.appendingPathComponent("blogs.json") + ) + + fileprivate static func resultDictionaryFrom( + directoryURL: URL, + by closure: @escaping (Data) throws -> SuccessValueType + ) throws -> ResultDictionary { + let xmlDataSet = Result { + try FileManager.default.dataFromDirectory(at: directoryURL) + } + + return + try xmlDataSet + .map { xmlDataSet in + xmlDataSet.flatResultMapValue(closure) + } + .map(Dictionary.init(uniqueKeysWithValues:)) + .get() + } } extension XMLCoder.XMLDecoder { - func decodeOPML(_ data: Data) throws -> OPML { + internal func decodeOPML(_ data: Data) throws -> OPML { try decode(OPML.self, from: data) } } diff --git a/Tests/SyndiKitTestSupport/Extensions/JSONFeed.swift b/Tests/SyndiKitTestSupport/Extensions/JSONFeed.swift index 8adb7747..8a907382 100644 --- a/Tests/SyndiKitTestSupport/Extensions/JSONFeed.swift +++ b/Tests/SyndiKitTestSupport/Extensions/JSONFeed.swift @@ -1,9 +1,9 @@ #if swift(<6.0) - import SyndiKit import Foundation + import SyndiKit #else - internal import SyndiKit internal import Foundation + internal import SyndiKit #endif extension JSONFeed { diff --git a/Tests/SyndiKitTestSupport/Extensions/SiteCollection.swift b/Tests/SyndiKitTestSupport/Extensions/SiteCollection.swift index 6f463d1b..3d528cb7 100644 --- a/Tests/SyndiKitTestSupport/Extensions/SiteCollection.swift +++ b/Tests/SyndiKitTestSupport/Extensions/SiteCollection.swift @@ -1,9 +1,9 @@ #if swift(<6.0) - import SyndiKit import Foundation + import SyndiKit #else - internal import SyndiKit internal import Foundation + internal import SyndiKit #endif extension SiteCollection { diff --git a/Tests/SyndiKitTestSupport/Extensions/String.swift b/Tests/SyndiKitTestSupport/Extensions/String.swift index aa9cb093..aa8bd21c 100644 --- a/Tests/SyndiKitTestSupport/Extensions/String.swift +++ b/Tests/SyndiKitTestSupport/Extensions/String.swift @@ -11,7 +11,7 @@ extension String { } internal func normalizeLineEndings() -> String { - return replacingOccurrences(of: "\r\n", with: "\n") + replacingOccurrences(of: "\r\n", with: "\n") .replacingOccurrences(of: "\r", with: "\n") } } diff --git a/Tests/SyndiKitTestSupport/Extensions/URL.swift b/Tests/SyndiKitTestSupport/Extensions/URL.swift index a0c807fd..d01abaae 100644 --- a/Tests/SyndiKitTestSupport/Extensions/URL.swift +++ b/Tests/SyndiKitTestSupport/Extensions/URL.swift @@ -5,7 +5,7 @@ #endif extension URL { - var remainingPath: String { + internal var remainingPath: String { let path = self.path return path == "/" ? "" : path diff --git a/Tests/SyndiKitTests/BlogTests.swift b/Tests/SyndiKitTests/BlogTests.swift index e8457c89..79d1b8a0 100644 --- a/Tests/SyndiKitTests/BlogTests.swift +++ b/Tests/SyndiKitTests/BlogTests.swift @@ -7,7 +7,7 @@ import XMLCoder @Suite("Blog Tests") internal struct BlogTests { @Test("Site category count validation") - func blogs() throws { + internal func blogs() throws { let blogs = Content.blogs let sites = SiteCollectionDirectory(blogs: blogs) diff --git a/Tests/SyndiKitTests/DecodingErrorTests.swift b/Tests/SyndiKitTests/DecodingErrorTests.swift index 782e41cd..5880de41 100644 --- a/Tests/SyndiKitTests/DecodingErrorTests.swift +++ b/Tests/SyndiKitTests/DecodingErrorTests.swift @@ -12,10 +12,10 @@ import Testing @Suite("Decoding Error Tests") internal struct DecodingErrorTests { @Test("Empty failed attempts returns data corrupted error") - func errorsEmpty() { + internal func errorsEmpty() { let error = DecodingError.failedAttempts([:]) - guard case let DecodingError.dataCorrupted(context) = error else { + guard case DecodingError.dataCorrupted(let context) = error else { Issue.record("Expected dataCorrupted error") return } @@ -24,13 +24,13 @@ internal struct DecodingErrorTests { } @Test("Single failed attempt returns nested data corrupted error") - func errorsOne() { + internal func errorsOne() { let debugDescription = UUID().uuidString let error = DecodingError.failedAttempts([ "Test": .dataCorrupted(.init(codingPath: [], debugDescription: debugDescription)) ]) - guard case let DecodingError.dataCorrupted(parentContext) = error else { + guard case DecodingError.dataCorrupted(let parentContext) = error else { Issue.record("Expected dataCorrupted error") return } @@ -40,7 +40,7 @@ internal struct DecodingErrorTests { return } - guard case let DecodingError.dataCorrupted(childContext) = decodingError else { + guard case DecodingError.dataCorrupted(let childContext) = decodingError else { Issue.record("Expected nested dataCorrupted error") return } @@ -49,14 +49,14 @@ internal struct DecodingErrorTests { } @Test("Multiple failed attempts returns error dictionary") - func errorsMany() { + internal func errorsMany() { let errors = [ "Test1": DecodingError.dataCorrupted(.init(codingPath: [], debugDescription: "")), "Test2": DecodingError.dataCorrupted(.init(codingPath: [], debugDescription: "")), ] let error = DecodingError.failedAttempts(errors) - guard case let DecodingError.dataCorrupted(context) = error else { + guard case DecodingError.dataCorrupted(let context) = error else { Issue.record("Expected dataCorrupted error") return } diff --git a/Tests/SyndiKitTests/EntryIDTests.swift b/Tests/SyndiKitTests/EntryIDTests.swift new file mode 100644 index 00000000..307b7e3f --- /dev/null +++ b/Tests/SyndiKitTests/EntryIDTests.swift @@ -0,0 +1,90 @@ +// +// EntryIDTests.swift +// SyndiKit +// +// Created by Leo Dion. +// Copyright © 2026 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import SyndiKit +import Testing + +#if swift(<6.0) + import Foundation +#else + internal import Foundation +#endif + +@Suite("Entry ID Tests") +internal struct EntryIDTests { + /// Builds every case of ``EntryID`` so each branch of + /// `init(string:)`, `description`, and Codable round-trips is exercised. + private static let samples: [(string: String, entryID: EntryID)] = { + let urlString = "https://example.com/post/1" + let uuidString = "e621e1f8-c36c-495a-93fc-0c247a3e6e5f" + var entries: [(string: String, entryID: EntryID)] = [] + if let url = URL(string: urlString) { + entries.append((urlString, .url(url))) + } + if let uuid = UUID(uuidString: uuidString) { + entries.append((uuidString, .uuid(uuid))) + } + entries.append(("yt:video:abc123", .path(["yt", "video", "abc123"], separatedBy: ":"))) + entries.append(("alpha/beta/gamma", .path(["alpha", "beta", "gamma"], separatedBy: "/"))) + entries.append(("plainstring", .string("plainstring"))) + return entries + }() + + @Test("init(string:) selects the expected case for every input") + internal func initStringBranches() { + for sample in Self.samples { + #expect(EntryID(string: sample.string) == sample.entryID) + } + } + + @Test("init?(_:) never returns nil and matches init(string:)") + internal func optionalInit() { + for sample in Self.samples { + #expect(EntryID(sample.string) == sample.entryID) + } + } + + @Test("description round-trips back to the original string for every case") + internal func descriptionForEachCase() { + for sample in Self.samples { + #expect(sample.entryID.description == sample.string) + } + } + + @Test("Codable round-trips every case through JSON") + internal func codableRoundTrip() throws { + let encoder = JSONEncoder() + let decoder = JSONDecoder() + for sample in Self.samples { + let data = try encoder.encode(sample.entryID) + let decoded = try decoder.decode(EntryID.self, from: data) + #expect(decoded == sample.entryID) + } + } +} diff --git a/Tests/SyndiKitTests/MediaPropertiesNilTests.swift b/Tests/SyndiKitTests/MediaPropertiesNilTests.swift new file mode 100644 index 00000000..15b1b8cf --- /dev/null +++ b/Tests/SyndiKitTests/MediaPropertiesNilTests.swift @@ -0,0 +1,99 @@ +// +// MediaPropertiesNilTests.swift +// SyndiKit +// +// Created by Leo Dion. +// Copyright © 2026 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Testing + +@testable import SyndiKit + +#if swift(<6.0) + import Foundation +#else + internal import Foundation +#endif + +@Suite("Media Properties Nil-Branch Tests") +internal struct MediaPropertiesNilTests { + /// A minimal RSS feed whose single item has no `` element. + private static let rssWithoutEnclosure = """ + + + + No Enclosure Channel + https://example.com + A channel without media enclosures. + + Plain Article + https://example.com/article + https://example.com/article + An article with no enclosure. + + + + """ + + /// A minimal Atom feed whose single entry has no YouTube channel/video IDs. + private static let atomWithoutYouTubeIDs = """ + + + No YouTube Feed + https://example.com/feed + 2026-01-01T00:00:00+00:00 + + + An Ordinary Entry + https://example.com/entry + 2026-01-01T00:00:00+00:00 + + + + """ + + @Test("PodcastEpisodeProperties(rssItem:) returns nil when there is no enclosure") + internal func podcastEpisodeWithoutEnclosure() throws { + let data = try #require(Self.rssWithoutEnclosure.data(using: .utf8)) + let feed = try SynDecoder().decode(data) + let rssFeed = try #require(feed as? RSSFeed) + let item = try #require(rssFeed.channel.items.first) + + #expect(item.enclosure == nil) + #expect(PodcastEpisodeProperties(rssItem: item) == nil) + } + + @Test("YouTubeIDProperties(entry:) returns nil for a non-YouTube Atom entry") + internal func youTubeIDPropertiesWithoutYouTubeIDs() throws { + let data = try #require(Self.atomWithoutYouTubeIDs.data(using: .utf8)) + let feed = try SynDecoder().decode(data) + let atomFeed = try #require(feed as? AtomFeed) + let entry = try #require(atomFeed.entries.first) + + #expect(entry.youtubeChannelID == nil) + #expect(entry.youtubeVideoID == nil) + #expect(YouTubeIDProperties(entry: entry) == nil) + } +} diff --git a/Tests/SyndiKitTests/RSSGUIDTests.swift b/Tests/SyndiKitTests/RSSGUIDTests.swift index 382167d3..31c396e6 100644 --- a/Tests/SyndiKitTests/RSSGUIDTests.swift +++ b/Tests/SyndiKitTests/RSSGUIDTests.swift @@ -10,14 +10,14 @@ import Testing #endif @Suite("RSS GUID Tests") -struct RSSGUIDTests { +internal struct RSSGUIDTests { @Test("Entry ID parses URL format") - func guidURL() { + internal func guidURL() { let urlString = "https://developer.apple.com/news/?id=jxky8h89" let urlGUID = EntryID(string: urlString) - guard case let .url(url) = urlGUID else { + guard case .url(let url) = urlGUID else { Issue.record("Expected .url case") return } @@ -25,13 +25,13 @@ struct RSSGUIDTests { } @Test("Entry ID parses UUID format") - func guidUUID() { + internal func guidUUID() { let expectedUUID = UUID() let expectedUUIDString = expectedUUID.uuidString let uuidGUID = EntryID(string: expectedUUIDString) - guard case let .uuid(actualUUID) = uuidGUID else { + guard case .uuid(let actualUUID) = uuidGUID else { Issue.record("Expected .uuid case") return } @@ -39,12 +39,12 @@ struct RSSGUIDTests { } @Test("Entry ID parses YouTube path format") - func guidYouTube() { + internal func guidYouTube() { let expectedPath = ["yt", "video", "3hccNoPE59U"] let pathGUID = EntryID(string: expectedPath.joined(separator: ":")) - guard case let .path(actualPath, ":") = pathGUID else { + guard case .path(let actualPath, ":") = pathGUID else { Issue.record("Expected .path case") return } diff --git a/Tests/SyndiKitTests/RSSItemCategoryTests.swift b/Tests/SyndiKitTests/RSSItemCategoryTests.swift index 3a39de85..517718eb 100644 --- a/Tests/SyndiKitTests/RSSItemCategoryTests.swift +++ b/Tests/SyndiKitTests/RSSItemCategoryTests.swift @@ -4,38 +4,38 @@ import Testing @testable import SyndiKitTestSupport @Suite("RSS Item Category Tests") -struct RSSItemCategoryTests { +internal struct RSSItemCategoryTests { @Test("Two equal categories are equal") - func twoEqualCategories() { - let c1 = RSSItemCategory( + internal func twoEqualCategories() { + let category1 = RSSItemCategory( value: "Top Menu", domain: "nav_menu", nicename: "top-menu" ) - let c2 = RSSItemCategory( + let category2 = RSSItemCategory( value: "Top Menu", domain: "nav_menu", nicename: "top-menu" ) - #expect(c1 == c2) + #expect(category1 == category2) } @Test("Two unequal categories are not equal") - func twoUnequalCategories() { - let c1 = RSSItemCategory( + internal func twoUnequalCategories() { + let category1 = RSSItemCategory( value: "Uncategorized", domain: "category", nicename: "uncategorized" ) - let c2 = RSSItemCategory( + let category2 = RSSItemCategory( value: "Top Menu", domain: "nav_menu", nicename: "top-menu" ) - #expect(c1 != c2) + #expect(category1 != category2) } } diff --git a/Tests/SyndiKitTests/SiteCollectionDirectoryBuilderTests.swift b/Tests/SyndiKitTests/SiteCollectionDirectoryBuilderTests.swift new file mode 100644 index 00000000..d96ae90f --- /dev/null +++ b/Tests/SyndiKitTests/SiteCollectionDirectoryBuilderTests.swift @@ -0,0 +1,59 @@ +// +// SiteCollectionDirectoryBuilderTests.swift +// SyndiKit +// +// Created by Leo Dion. +// Copyright © 2026 BrightDigit. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// + +import Testing + +@testable import SyndiKit +@testable import SyndiKitTestSupport + +@Suite("Site Collection Directory Builder Tests") +internal struct SiteCollectionDirectoryBuilderTests { + @Test("Builder produces a directory equivalent to the direct initializer") + internal func directoryFromCollection() { + let blogs = Content.blogs + let builder = SiteCollectionDirectoryBuilder() + + let builtDirectory = builder.directory(fromCollection: blogs) + let expectedDirectory = SiteCollectionDirectory(blogs: blogs) + + for languageContent in blogs { + for category in languageContent.categories { + let builtSites = builtDirectory.sites( + withLanguage: languageContent.language, + withCategory: category.slug + ) + let expectedSites = expectedDirectory.sites( + withLanguage: languageContent.language, + withCategory: category.slug + ) + #expect(builtSites.count == expectedSites.count) + } + } + } +} diff --git a/Tests/SyndiKitTests/UTF8EncodedURLTests.swift b/Tests/SyndiKitTests/UTF8EncodedURLTests.swift index 48c08297..2c86c5a3 100644 --- a/Tests/SyndiKitTests/UTF8EncodedURLTests.swift +++ b/Tests/SyndiKitTests/UTF8EncodedURLTests.swift @@ -13,8 +13,8 @@ import XMLCoder @Suite("UTF8 Encoded URL Tests") internal struct UTF8EncodedURLTests { @Test("Decode UTF8 encoded URL from JSON") - func decode() throws { - let expectedURL = URL(strict: "http://www.example.com/index.php")! + internal func decode() throws { + let expectedURL = try #require(URL(strict: "http://www.example.com/index.php")) let urlStr = """ "\(expectedURL)" """ diff --git a/Tests/SyndiKitTests/WordPressElementsTests.swift b/Tests/SyndiKitTests/WordPressElementsTests.swift index 12f5fb1b..b695a7e7 100644 --- a/Tests/SyndiKitTests/WordPressElementsTests.swift +++ b/Tests/SyndiKitTests/WordPressElementsTests.swift @@ -4,45 +4,45 @@ import Testing @testable import SyndiKitTestSupport @Suite("WordPress Elements Tests") -struct WordPressElementsTests { +internal struct WordPressElementsTests { @Test("WordPress categories with different IDs are not equal") - func categoryEquatable() { - let c1 = WordPressElements.Category( + internal func categoryEquatable() { + let category1 = WordPressElements.Category( termID: 1, nicename: .init(stringLiteral: "uncategorized"), parent: .init(stringLiteral: ""), name: "Uncategorized" ) - let c2 = WordPressElements.Category( + let category2 = WordPressElements.Category( termID: 2, nicename: .init(stringLiteral: "podcasting"), parent: .init(stringLiteral: ""), name: "Podcasting" ) - #expect(c1 != c2) + #expect(category1 != category2) } @Test("WordPress tags with different IDs are not equal") - func tagEquatable() { - let t1 = WordPressElements.Tag( + internal func tagEquatable() { + let tag1 = WordPressElements.Tag( termID: 1, slug: .init(stringLiteral: "uncategorized"), name: .init(stringLiteral: "uncategorized") ) - let t2 = WordPressElements.Tag( + let tag2 = WordPressElements.Tag( termID: 2, slug: .init(stringLiteral: "podcasting"), name: .init(stringLiteral: "Podcasting") ) - #expect(t1 != t2) + #expect(tag1 != tag2) } @Test("WordPress post meta with different keys are not equal") - func postMetaEquatable() { + internal func postMetaEquatable() { let pm1 = WordPressElements.PostMeta( key: "_edit_last", value: "1" diff --git a/Tests/SyndiKitTests/XMLStringIntTests.swift b/Tests/SyndiKitTests/XMLStringIntTests.swift index 241125c9..ba3ab341 100644 --- a/Tests/SyndiKitTests/XMLStringIntTests.swift +++ b/Tests/SyndiKitTests/XMLStringIntTests.swift @@ -13,7 +13,7 @@ import XMLCoder @Suite("XML String Int Tests") internal struct XMLStringIntTests { @Test("Decode valid XML integer value") - func decodeValidXMLValue() throws { + internal func decodeValidXMLValue() throws { let expectedAge = 10 let xmlStr = """ \(expectedAge) @@ -27,7 +27,7 @@ internal struct XMLStringIntTests { } @Test("Decode invalid XML integer value throws error") - func decodeInvalidXMLValue() throws { + internal func decodeInvalidXMLValue() throws { let xmlStr = """ invalid """ diff --git a/Tests/SyndiKitXCTests/AuthorParsingTests.swift b/Tests/SyndiKitXCTests/AuthorParsingTests.swift index 5eb0afeb..d545b372 100644 --- a/Tests/SyndiKitXCTests/AuthorParsingTests.swift +++ b/Tests/SyndiKitXCTests/AuthorParsingTests.swift @@ -27,6 +27,8 @@ // OTHER DEALINGS IN THE SOFTWARE. // +// swiftlint:disable file_length + import XCTest import XMLCoder @@ -38,13 +40,14 @@ import XMLCoder #elseif swift(<6.0) import Foundation #else - public import Foundation + internal import Foundation #endif -final class AuthorParsingTests: XCTestCase { +// swiftlint:disable:next type_body_length +internal final class AuthorParsingTests: XCTestCase { // MARK: - RFC 822 Format Tests - func testAuthorWithEmailAndName() throws { + internal func testAuthorWithEmailAndName() throws { let xml = """ podcast@example.com (Jane Doe) """ @@ -59,7 +62,7 @@ final class AuthorParsingTests: XCTestCase { XCTAssertNil(author.uri) } - func testAuthorWithEmailOnly() throws { + internal func testAuthorWithEmailOnly() throws { let xml = """ webmaster@example.com """ @@ -74,7 +77,7 @@ final class AuthorParsingTests: XCTestCase { XCTAssertNil(author.uri) } - func testAuthorWithNameOnly() throws { + internal func testAuthorWithNameOnly() throws { let xml = """ John Doe """ @@ -89,7 +92,7 @@ final class AuthorParsingTests: XCTestCase { XCTAssertNil(author.uri) } - func testAuthorWithComplexName() throws { + internal func testAuthorWithComplexName() throws { let xml = """ doctor@example.com (Dr. John Q. Doe, Jr.) """ @@ -104,7 +107,7 @@ final class AuthorParsingTests: XCTestCase { XCTAssertNil(author.uri) } - func testAuthorWithExtraWhitespace() throws { + internal func testAuthorWithExtraWhitespace() throws { let xml = """ podcast@example.com ( Jane Doe ) """ @@ -121,7 +124,7 @@ final class AuthorParsingTests: XCTestCase { // MARK: - Edge Cases - func testAuthorWithEmptyString() throws { + internal func testAuthorWithEmptyString() throws { let xml = """ """ @@ -136,7 +139,7 @@ final class AuthorParsingTests: XCTestCase { XCTAssertNil(author.uri) } - func testAuthorWithMultipleParentheses() throws { + internal func testAuthorWithMultipleParentheses() throws { let xml = """ test@example.com (John (Johnny) Doe) """ @@ -152,7 +155,7 @@ final class AuthorParsingTests: XCTestCase { XCTAssertNil(author.uri) } - func testInternationalCharacters() throws { + internal func testInternationalCharacters() throws { let xml = """ test@example.com (François Müller) """ @@ -169,7 +172,7 @@ final class AuthorParsingTests: XCTestCase { // MARK: - Malformed Input Tests - func testUnclosedParenthesis() throws { + internal func testUnclosedParenthesis() throws { let xml = """ email@example.com (Name Without Closing """ @@ -185,7 +188,7 @@ final class AuthorParsingTests: XCTestCase { XCTAssertNil(author.uri) } - func testMultipleAtSymbols() throws { + internal func testMultipleAtSymbols() throws { let xml = """ user@@domain.com """ @@ -201,7 +204,7 @@ final class AuthorParsingTests: XCTestCase { XCTAssertNil(author.uri) } - func testTextAfterParenthesis() throws { + internal func testTextAfterParenthesis() throws { let xml = """ email@example.com (Display Name) extra text """ @@ -217,7 +220,7 @@ final class AuthorParsingTests: XCTestCase { XCTAssertNil(author.uri) } - func testEmptyParentheses() throws { + internal func testEmptyParentheses() throws { let xml = """ email@example.com () """ @@ -233,7 +236,7 @@ final class AuthorParsingTests: XCTestCase { XCTAssertNil(author.uri) } - func testLeadingAtSymbol() throws { + internal func testLeadingAtSymbol() throws { let xml = """ @example.com """ @@ -249,7 +252,7 @@ final class AuthorParsingTests: XCTestCase { XCTAssertNil(author.uri) } - func testTrailingAtSymbol() throws { + internal func testTrailingAtSymbol() throws { let xml = """ username@ """ @@ -265,7 +268,7 @@ final class AuthorParsingTests: XCTestCase { XCTAssertNil(author.uri) } - func testOnlyAtSymbol() throws { + internal func testOnlyAtSymbol() throws { let xml = """ @ """ @@ -283,7 +286,7 @@ final class AuthorParsingTests: XCTestCase { // MARK: - Atom Format Backward Compatibility - func testAtomAuthorStillWorks() throws { + internal func testAtomAuthorStillWorks() throws { let xml = """ Jane Doe @@ -302,7 +305,7 @@ final class AuthorParsingTests: XCTestCase { XCTAssertEqual(author.uri, URL(string: "https://example.com")) } - func testAtomAuthorWithOnlyName() throws { + internal func testAtomAuthorWithOnlyName() throws { let xml = """ Jane Doe @@ -321,7 +324,7 @@ final class AuthorParsingTests: XCTestCase { // MARK: - Encoding Tests - func testAuthorRoundTrip() throws { + internal func testAuthorRoundTrip() throws { let original = Author( name: "Jane Doe", email: "jane@example.com", @@ -339,7 +342,7 @@ final class AuthorParsingTests: XCTestCase { XCTAssertEqual(decoded.uri, original.uri) } - func testAuthorRoundTripWithoutEmail() throws { + internal func testAuthorRoundTripWithoutEmail() throws { let original = Author(name: "Jane Doe", email: nil, uri: nil) let encoder = XMLCoder.XMLEncoder() @@ -355,7 +358,7 @@ final class AuthorParsingTests: XCTestCase { // MARK: - Existing API Compatibility - func testPublicInitializerStillWorks() { + internal func testPublicInitializerStillWorks() { let author = Author(name: "Jane Doe") XCTAssertEqual(author.name, "Jane Doe") diff --git a/Tests/SyndiKitXCTests/OPMLTests.swift b/Tests/SyndiKitXCTests/OPMLTests.swift index 6f9cb3ae..0e593e25 100644 --- a/Tests/SyndiKitXCTests/OPMLTests.swift +++ b/Tests/SyndiKitXCTests/OPMLTests.swift @@ -16,14 +16,18 @@ internal final class OPMLTests: XCTestCase { XCTAssertEqual(firstOutline?.text, "CNET News.com") XCTAssertEqual( firstOutline?.description, - "Tech news and business reports by CNET News.com. Focused on information technology, core topics include computers, hardware, software, networking, and Internet media." + "Tech news and business reports by CNET News.com. Focused on information technology, " + + "core topics include computers, hardware, software, networking, and Internet media." ) - XCTAssertEqual(firstOutline?.htmlUrl, URL(string: "http://news.com.com/")!) + XCTAssertEqual(firstOutline?.htmlUrl, try XCTUnwrap(URL(string: "http://news.com.com/"))) XCTAssertEqual(firstOutline?.language, "unknown") XCTAssertEqual(firstOutline?.title, "CNET News.com") XCTAssertEqual(firstOutline?.type, .rss) XCTAssertEqual(firstOutline?.version, "RSS2") - XCTAssertEqual(firstOutline?.xmlUrl, URL(string: "http://news.com.com/2547-1_3-0-5.xml")!) + XCTAssertEqual( + firstOutline?.xmlUrl, + try XCTUnwrap(URL(string: "http://news.com.com/2547-1_3-0-5.xml")) + ) } internal func testStates() throws { @@ -93,7 +97,7 @@ internal final class OPMLTests: XCTestCase { internal func testInvalidExpansionStateType() throws { XCTAssertThrowsError(try Content.opml["category_invalidExpansionState"]?.get()) { error in - guard case let .typeMismatch(type, context) = error as? DecodingError else { + guard case .typeMismatch(let type, let context) = error as? DecodingError else { XCTFail("Expected typeMismatch error.") return } diff --git a/Tests/SyndiKitXCTests/RSSCoded.Durations.swift b/Tests/SyndiKitXCTests/RSSCoded.Durations.swift index 4bf71925..182e46dc 100644 --- a/Tests/SyndiKitXCTests/RSSCoded.Durations.swift +++ b/Tests/SyndiKitXCTests/RSSCoded.Durations.swift @@ -1,3 +1,5 @@ +// swiftlint:disable:this file_name + @testable import SyndiKitTestSupport #if swift(<6.0) diff --git a/Tests/SyndiKitXCTests/RSSCodedTests.swift b/Tests/SyndiKitXCTests/RSSCodedTests.swift index f2bbd9d7..60181644 100644 --- a/Tests/SyndiKitXCTests/RSSCodedTests.swift +++ b/Tests/SyndiKitXCTests/RSSCodedTests.swift @@ -1,3 +1,6 @@ +// swiftlint:disable:this file_name +// swiftlint:disable file_length + import XCTest import XMLCoder @@ -14,15 +17,24 @@ import XMLCoder /// because these properties are compile-time disabled due to FileManager limitations /// and memory constraints. Core parsing is validated via inline XML test fixtures. @available(macOS 13.0, *) +// swiftlint:disable:next type_body_length internal final class SyndiKitTests: XCTestCase { - static let itemCount = 20 + internal static let itemCount = 20 + + private static let hostImageURLString = + "https://images.transistor.fm/file/transistor/images/person/" + + "401f05b8-f63f-4b96-803f-c7ac9233b459/1664979700-image.jpg" + + private static let guestImageURLString = + "https://images.transistor.fm/file/transistor/images/person/" + + "e36ebf22-69fa-4e4f-a79b-1348c4d39267/1668262451-image.jpg" #if os(WASI) private static let wasiSkipMessage = "Test requires xmlFeeds/jsonFeeds properties not available on WASI platform (memory constraints)" #endif - func testCategories() throws { + internal func testCategories() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -107,7 +119,7 @@ internal final class SyndiKitTests: XCTestCase { } } - func testEntryable() throws { + internal func testEntryable() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -161,7 +173,7 @@ internal final class SyndiKitTests: XCTestCase { } } - func testJSONXMLEquality() throws { + internal func testJSONXMLEquality() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -189,7 +201,8 @@ internal final class SyndiKitTests: XCTestCase { }), rss.children.sorted(by: { $0.title < $1.title - })) + }) + ) for (jsonItem, rssItem) in items { XCTAssertEqual( @@ -207,7 +220,7 @@ internal final class SyndiKitTests: XCTestCase { #endif } - func testChannelPodcastElements() throws { + internal func testChannelPodcastElements() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -239,14 +252,12 @@ internal final class SyndiKitTests: XCTestCase { XCTAssertEqual(person.href, URL(strict: "https://brightdigit.com")) XCTAssertEqual( person.img, - URL( - strict: - "https://images.transistor.fm/file/transistor/images/person/401f05b8-f63f-4b96-803f-c7ac9233b459/1664979700-image.jpg" - )) + URL(strict: Self.hostImageURLString) + ) #endif } - func testItemPodcastElements() throws { + internal func testItemPodcastElements() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -272,10 +283,8 @@ internal final class SyndiKitTests: XCTestCase { XCTAssertEqual(host.href, URL(strict: "https://brightdigit.com")) XCTAssertEqual( host.img, - URL( - strict: - "https://images.transistor.fm/file/transistor/images/person/401f05b8-f63f-4b96-803f-c7ac9233b459/1664979700-image.jpg" - )) + URL(strict: Self.hostImageURLString) + ) let guest = item.podcastPeople[1] XCTAssertEqual(guest.fullname, "CompileSwift") @@ -283,27 +292,29 @@ internal final class SyndiKitTests: XCTestCase { XCTAssertEqual(guest.href, URL(strict: "https://compileswift.com")) XCTAssertEqual( guest.img, - URL( - strict: - "https://images.transistor.fm/file/transistor/images/person/e36ebf22-69fa-4e4f-a79b-1348c4d39267/1668262451-image.jpg" - )) + URL(strict: Self.guestImageURLString) + ) XCTAssertEqual(item.podcastTranscripts.count, 1) let transcript = item.podcastTranscripts[0] XCTAssertEqual( - transcript.url, URL(strict: "https://share.transistor.fm/s/336118a1/transcript.srt")!) + transcript.url, + try XCTUnwrap(URL(strict: "https://share.transistor.fm/s/336118a1/transcript.srt")) + ) XCTAssertEqual(transcript.type, .srt) XCTAssertEqual(transcript.rel, .captions) let chapters = item.podcastChapters XCTAssertEqual( - chapters?.url, URL(strict: "https://share.transistor.fm/s/336118a1/chapters.json")!) + chapters?.url, + try XCTUnwrap(URL(strict: "https://share.transistor.fm/s/336118a1/chapters.json")) + ) XCTAssertEqual(chapters?.type, .json) #endif } - func testPodcastPeopleUnknownRole() throws { + internal func testPodcastPeopleUnknownRole() throws { let expectedRole = "worker" let xmlStr = """ Austin, TX - + """ guard let data = xmlStr.data(using: .utf8) else { @@ -392,9 +403,9 @@ internal final class SyndiKitTests: XCTestCase { XCTAssertNil(sut.osmQuery?.revision) } - func testPodcastLocationWithAccuracy() throws { - let expectedLatitude = 30.267_2 - let expectedLongitude = 97.743_1 + internal func testPodcastLocationWithAccuracy() throws { + let expectedLatitude = 30.2672 + let expectedLongitude = 97.7431 let expectedAccuracy = 350.0 let xmlStr = """ Austin, TX - + """ guard let data = xmlStr.data(using: .utf8) else { @@ -416,13 +427,15 @@ internal final class SyndiKitTests: XCTestCase { XCTAssertEqual(sut.geo?.longitude, expectedLongitude) XCTAssertEqual(sut.geo?.accuracy, expectedAccuracy) XCTAssertEqual( - sut.geo?.description, "geo:\(expectedLatitude),\(expectedLongitude);u=\(expectedAccuracy)") + sut.geo?.description, + "geo:\(expectedLatitude),\(expectedLongitude);u=\(expectedAccuracy)" + ) XCTAssertNil(sut.geo?.altitude) } - func testPodcastLocationWithAltitude() throws { - let expectedLatitude = 30.267_2 - let expectedLongitude = 97.743_1 + internal func testPodcastLocationWithAltitude() throws { + let expectedLatitude = 30.2672 + let expectedLongitude = 97.7431 let expectedAltitude = 250.0 let xmlStr = """ Austin, TX - + """ guard let data = xmlStr.data(using: .utf8) else { @@ -444,11 +457,13 @@ internal final class SyndiKitTests: XCTestCase { XCTAssertEqual(sut.geo?.longitude, expectedLongitude) XCTAssertEqual(sut.geo?.altitude, expectedAltitude) XCTAssertEqual( - sut.geo?.description, "geo:\(expectedLatitude),\(expectedLongitude),\(expectedAltitude)") + sut.geo?.description, + "geo:\(expectedLatitude),\(expectedLongitude),\(expectedAltitude)" + ) XCTAssertNil(sut.geo?.accuracy) } - func testPodcastLocationWithInvalidGeoData() throws { + internal func testPodcastLocationWithInvalidGeoData() throws { let missingGeoScheme = """ Austin, TX """ @@ -466,7 +481,7 @@ internal final class SyndiKitTests: XCTestCase { try assertInvalidGeoData(from: invalidCoords) } - func testPodcastMissingLink() throws { + internal func testPodcastMissingLink() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -505,7 +520,7 @@ internal final class SyndiKitTests: XCTestCase { } } - func testPodcastLocationWithInvalidOsmData() throws { + internal func testPodcastLocationWithInvalidOsmData() throws { let invalidOsmType = """ Austin, TX """ @@ -537,9 +552,9 @@ internal final class SyndiKitTests: XCTestCase { ) { guard let decodingError = error as? DecodingError, - case let DecodingError.dataCorrupted(context) = decodingError + case DecodingError.dataCorrupted(let context) = decodingError else { - XCTFail() + XCTFail("Expected DecodingError.dataCorrupted, got \(error)") return } @@ -550,7 +565,7 @@ internal final class SyndiKitTests: XCTestCase { ) } - func testPodcastEpisodes() throws { + internal func testPodcastEpisodes() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -563,7 +578,7 @@ internal final class SyndiKitTests: XCTestCase { "ideveloper": 276...297, "it-guy": 1...330, ].mapValues { - [Int]($0.map { $0 }.reversed()) + Array($0.reversed()) } for (name, episodeNumbers) in podcasts { @@ -598,7 +613,7 @@ internal final class SyndiKitTests: XCTestCase { #endif } - func testEpisodeStringSummary() throws { + internal func testEpisodeStringSummary() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -626,7 +641,7 @@ internal final class SyndiKitTests: XCTestCase { #endif } - func testEpisodesWithNoPersons() throws { + internal func testEpisodesWithNoPersons() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -652,7 +667,7 @@ internal final class SyndiKitTests: XCTestCase { #endif } - func testEpisodesWithHostAndGuestPersons() throws { + internal func testEpisodesWithHostAndGuestPersons() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -682,10 +697,7 @@ internal final class SyndiKitTests: XCTestCase { XCTAssertEqual(host?.href, URL(strict: "https://brightdigit.com")) XCTAssertEqual( host?.img, - URL( - string: - "https://images.transistor.fm/file/transistor/images/person/401f05b8-f63f-4b96-803f-c7ac9233b459/1664979700-image.jpg" - ) + URL(string: Self.hostImageURLString) ) // Both podcasts have the same guest @@ -696,16 +708,13 @@ internal final class SyndiKitTests: XCTestCase { XCTAssertEqual(guest?.href, URL(strict: "https://compileswift.com")) XCTAssertEqual( guest?.img, - URL( - string: - "https://images.transistor.fm/file/transistor/images/person/e36ebf22-69fa-4e4f-a79b-1348c4d39267/1668262451-image.jpg" - ) + URL(string: Self.guestImageURLString) ) } #endif } - func testEpisodeCDataSummary() throws { + internal func testEpisodeCDataSummary() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -733,7 +742,7 @@ internal final class SyndiKitTests: XCTestCase { #endif } - func testSyndication() throws { + internal func testSyndication() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -762,14 +771,24 @@ internal final class SyndiKitTests: XCTestCase { #endif } - // swiftlint:disable:next function_body_length - func testYoutubeVideos() throws { + private func youtubeID(from item: any Entryable) -> (any YouTubeID)? { + item.media.flatMap { media -> (any YouTubeID)? in + guard case .video(let video) = media else { + return nil + } + guard case .youtube(let youtube) = video else { + return nil + } + return youtube + } + } + + internal func testYoutubeVideos() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else for (name, xmlResult) in Content.xmlFeeds where name.hasSuffix("youtube") { - let feed: any Feedable do { feed = try xmlResult.get() @@ -779,22 +798,14 @@ internal final class SyndiKitTests: XCTestCase { } guard let atom = feed as? AtomFeed else { - XCTFail() + XCTFail("Expected AtomFeed for \(name)") continue } let items = zip(atom.entries, feed.children) for (entry, item) in items { - let youtube = item.media.flatMap { media -> (any YouTubeID)? in - guard case let .video(video) = media else { - return nil - } - guard case let .youtube(youtube) = video else { - return nil - } - return youtube - } + let youtube = youtubeID(from: item) guard let group = entry.mediaGroup else { XCTAssertNotNil(entry.mediaGroup) continue @@ -810,7 +821,7 @@ internal final class SyndiKitTests: XCTestCase { #endif } - func testDurations() throws { + internal func testDurations() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -829,7 +840,7 @@ internal final class SyndiKitTests: XCTestCase { let actuals = rss.channel.items.compactMap { $0.itunesDuration?.value } let durations = feed.children.map { $0.media.flatMap { media -> TimeInterval? in - if case let .podcast(episode) = media { + if case .podcast(let episode) = media { return episode.duration } else { return nil @@ -850,7 +861,7 @@ internal final class SyndiKitTests: XCTestCase { // MARK: - Author Parsing Integration Tests - func testRaywenderlichManagingEditor() throws { + internal func testRaywenderlichManagingEditor() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -875,7 +886,8 @@ internal final class SyndiKitTests: XCTestCase { #endif } - func testNewsRSSManagingEditorAndWebMaster() throws { + // swiftlint:disable:next inclusive_language + internal func testNewsRSSManagingEditorAndWebMaster() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else diff --git a/Tests/SyndiKitXCTests/WordpressTests.swift b/Tests/SyndiKitXCTests/WordpressTests.swift index 1c9fb68c..9f9fbe52 100644 --- a/Tests/SyndiKitXCTests/WordpressTests.swift +++ b/Tests/SyndiKitXCTests/WordpressTests.swift @@ -1,3 +1,5 @@ +// swiftlint:disable file_length + import XCTest @testable import SyndiKit @@ -9,23 +11,26 @@ import XCTest internal import Foundation #endif -final class WordpressTests: XCTestCase { - static let baseSiteURLs: [String: URL] = [ +// swiftlint:disable:next type_body_length +internal final class WordpressTests: XCTestCase { + // swiftlint:disable force_unwrapping + internal static let baseSiteURLs: [String: URL] = [ "articles": URL(string: "https://brightdigit.com/")!, "tutorials": URL(string: "https://brightdigit.com/")!, ] - static let baseBlogURLs: [String: URL] = [ + internal static let baseBlogURLs: [String: URL] = [ "articles": URL(string: "https://brightdigit.com")!, "tutorials": URL(string: "https://learningswift.brightdigit.com")!, ] + // swiftlint:enable force_unwrapping #if os(WASI) private static let wasiSkipMessage = "Test requires wordpressDataSet not available on WASI platform (memory constraints)" #endif - func testDateDecoderRFC822() throws { + internal func testDateDecoderRFC822() throws { #if os(WASI) throw XCTSkip( "RFC 822 date format requires ICU locale data for month/day names, " @@ -41,7 +46,7 @@ final class WordpressTests: XCTestCase { #endif } - func testDateDecoderWordPressCustomFormat() { + internal func testDateDecoderWordPressCustomFormat() { let dateDecoder = DateFormatterDecoder.RSS.decoder let result = dateDecoder.decodeString("2017-10-06 16:59:50") XCTAssertNotNil( @@ -50,9 +55,8 @@ final class WordpressTests: XCTestCase { ) } - // swiftlint:disable:next function_body_length @available(macOS 13.0, *) - func testWordpressPosts() throws { + internal func testWordpressPosts() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -77,7 +81,7 @@ final class WordpressTests: XCTestCase { } guard let feed = feedable as? RSSFeed else { - XCTFail() + XCTFail("Expected RSSFeed for \(name)") continue } @@ -100,9 +104,9 @@ final class WordpressTests: XCTestCase { #endif } - func testInitMissingName() { + internal func testInitMissingName() throws { let urlString = "https://developer.apple.com/news/?id=jxky8h89" - let url = URL(strict: urlString)! + let url = try XCTUnwrap(URL(strict: urlString)) let itemMissingName = RSSItem( title: UUID().uuidString, link: url, @@ -117,9 +121,9 @@ final class WordpressTests: XCTestCase { } // swiftlint:disable:next function_body_length - func testInitAllFields() { + internal func testInitAllFields() throws { let urlString = "https://developer.apple.com/news/?id=jxky8h89" - let url = URL(strict: urlString)! + let url = try XCTUnwrap(URL(strict: urlString)) let title = UUID().uuidString let description = UUID().uuidString @@ -185,9 +189,9 @@ final class WordpressTests: XCTestCase { } // swiftlint:disable:next function_body_length - func testInitAllFieldsMeta() { + internal func testInitAllFieldsMeta() throws { let urlString = "https://developer.apple.com/news/?id=jxky8h89" - let url = URL(strict: urlString)! + let url = try XCTUnwrap(URL(strict: urlString)) let title = UUID().uuidString let description = UUID().uuidString @@ -272,9 +276,9 @@ final class WordpressTests: XCTestCase { } // swiftlint:disable:next function_body_length - func testInitAllFieldsWMeta() { + internal func testInitAllFieldsWMeta() throws { let urlString = "https://developer.apple.com/news/?id=jxky8h89" - let url = URL(strict: urlString)! + let url = try XCTUnwrap(URL(strict: urlString)) let title = UUID().uuidString let description = UUID().uuidString @@ -356,9 +360,8 @@ final class WordpressTests: XCTestCase { XCTAssertEqual(post.tags, postTags) } - // swiftlint:disable:next function_body_length @available(macOS 13.0, *) - func testWpAttachmentURL() throws { + internal func testWpAttachmentURL() throws { #if os(WASI) throw XCTSkip(Self.wasiSkipMessage) #else @@ -383,15 +386,17 @@ final class WordpressTests: XCTestCase { } guard let feed = feedable as? RSSFeed else { - XCTFail() + XCTFail("Expected RSSFeed for \(name)") continue } - let items = feed.channel.items.compactMap { item in - (try? WordPressPost(item: item)).map { (item, $0) } - }.filter { - $0.1.type == "attachment" - } + let items = feed.channel.items + .compactMap { item in + (try? WordPressPost(item: item)).map { (item, $0) } + } + .filter { + $0.1.type == "attachment" + } for (item, post) in items { XCTAssertNotNil(item.wpAttachmentURL)