From 31f6a6cbc2af6e20bab508e7618ce33e84918504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20R=C3=B6nnqvist?= Date: Fri, 8 Nov 2024 11:16:07 +0100 Subject: [PATCH] Revert "Temporarily avoid using FoundationXML to unblock CI (#1090)" This reverts commit 6ace3efe7ae526aac53e2c345db95d106661391e. --- .../Bundle Assets/SVGIDExtractor.swift | 48 +++++++++++++------ .../Variants/JSONPatchOperation.swift | 9 ---- .../Infrastructure/SVGIDExtractorTests.swift | 13 ----- 3 files changed, 34 insertions(+), 36 deletions(-) diff --git a/Sources/SwiftDocC/Infrastructure/Bundle Assets/SVGIDExtractor.swift b/Sources/SwiftDocC/Infrastructure/Bundle Assets/SVGIDExtractor.swift index 4a5f8ab558..02e50794ee 100644 --- a/Sources/SwiftDocC/Infrastructure/Bundle Assets/SVGIDExtractor.swift +++ b/Sources/SwiftDocC/Infrastructure/Bundle Assets/SVGIDExtractor.swift @@ -1,7 +1,7 @@ /* This source file is part of the Swift.org open source project - Copyright (c) 2022-2024 Apple Inc. and the Swift project authors + Copyright (c) 2022 Apple Inc. and the Swift project authors Licensed under Apache License v2.0 with Runtime Library Exception See https://swift.org/LICENSE.txt for license information @@ -10,6 +10,12 @@ import Foundation +// On non-Darwin platforms, Foundation's XML support is vended as a separate module: +// https://github.com/apple/swift-corelibs-foundation/blob/main/Docs/ReleaseNotes_Swift5.md#dependency-management +#if canImport(FoundationXML) +import FoundationXML +#endif + /// A basic XML parser that extracts the first `id` attribute found in the given SVG. /// /// This is a single-purpose tool and should not be used for general-purpose SVG parsing. @@ -19,19 +25,14 @@ enum SVGIDExtractor { /// Exposed for testing. The sibling `extractID(from: URL)` method is intended to be /// used within SwiftDocC. static func _extractID(from data: Data) -> String? { - // FIXME: Revert this and resume using XMLParser when rdar://138726860 is integrated into a Swift toolchain. - for capitalization in ["id", "ID", "Id", "iD"] { - guard let idAttributeRange = data.firstRange(of: Data(" \(capitalization)=\"".utf8), in: data.indices) else { - continue - } - - guard let endQuote = data.firstRange(of: Data("\"".utf8), in: idAttributeRange.upperBound...) else { - continue - } - - return String(data: data[idAttributeRange.endIndex ..< endQuote.lowerBound], encoding: .utf8) - } - return nil + let delegate = SVGIDParserDelegate() + let svgParser = XMLParser(data: data) + svgParser.delegate = delegate + + // The delegate aborts the parsing when it finds the ID so the larger parsing operation is not "successful" + _ = svgParser.parse() + + return delegate.id } /// Returns the first `id` attribute found in the given SVG, if any. @@ -46,3 +47,22 @@ enum SVGIDExtractor { return _extractID(from: data) } } + +private class SVGIDParserDelegate: NSObject, XMLParserDelegate { + var id: String? + + func parser( + _ parser: XMLParser, + didStartElement elementName: String, + namespaceURI: String?, + qualifiedName qName: String?, + attributes attributeDict: [String : String] = [:] + ) { + guard let id = attributeDict["id"] ?? attributeDict["ID"] ?? attributeDict["iD"] ?? attributeDict["Id"] else { + return + } + + self.id = id + parser.abortParsing() + } +} diff --git a/Sources/SwiftDocC/Model/Rendering/Variants/JSONPatchOperation.swift b/Sources/SwiftDocC/Model/Rendering/Variants/JSONPatchOperation.swift index 48a6252847..109e46bfd2 100644 --- a/Sources/SwiftDocC/Model/Rendering/Variants/JSONPatchOperation.swift +++ b/Sources/SwiftDocC/Model/Rendering/Variants/JSONPatchOperation.swift @@ -74,15 +74,6 @@ public enum JSONPatchOperation: Codable { /// - variantPatchOperation: The patch to apply. /// - pointer: The pointer to the value to update. public init(variantPatchOperation: VariantPatchOperation, pointer: JSONPointer) { - // FIXME: The latest Swift development snapshots (2024-10-30-a and later) is missing the "references" path component. (rdar://139446585) - // AFAICT it's the only path that's missing components, so we're working around that issue here. - // Since the only RenderNode coding paths that have include a topic reference (as its 2nd component) are - // modifications of topics in the "references" section, we can detect and workaround this issue by checking for a "doc://" prefix. - var pointer = pointer - if pointer.pathComponents.first?.hasPrefix("doc://") == true { - pointer = pointer.prependingPathComponents(["references"]) - } - switch variantPatchOperation { case .replace(let value): self = .replace(pointer: pointer, encodableValue: value) diff --git a/Tests/SwiftDocCTests/Infrastructure/SVGIDExtractorTests.swift b/Tests/SwiftDocCTests/Infrastructure/SVGIDExtractorTests.swift index 92b6904625..1026af9d55 100644 --- a/Tests/SwiftDocCTests/Infrastructure/SVGIDExtractorTests.swift +++ b/Tests/SwiftDocCTests/Infrastructure/SVGIDExtractorTests.swift @@ -25,19 +25,6 @@ class SVGIDExtractorTests: XCTestCase { XCTAssertEqual(id, "plus-id") } - do { - let id = extractIDFromSVG( - """ - - - - - """ - ) - - XCTAssertEqual(id, "plus-id") - } - do { let id = extractIDFromSVG( """