Skip to content

Commit

Permalink
Fix a doc anchor is not encoded correctly (#867) (#914)
Browse files Browse the repository at this point in the history
* Fix a doc anchor is not encoded correctly

* Add a test for rendering heading anchors

* Pass stored unencoded fragment

* Remove the unsuitable test case

Also apply suggestions from code review.

* Apply suggestions from code review

* Treat a link destination as the "authored link"

* Revert "Treat a link destination as the "authored link""

This reverts commit 4e3f8da.

* Mark the test article as a technology root

Co-authored-by: Hironori Ichimiya <[email protected]>

rdar://127870203
  • Loading branch information
d-ronnqvist committed May 10, 2024
1 parent 75ab930 commit 6a47d16
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Sources/SwiftDocC/Infrastructure/NodeURLGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ public struct NodeURLGenerator {
)
} else {
let url = baseURL.appendingPathComponent(safePath, isDirectory: false)
return url.withFragment(reference.url.fragment)
return url.withFragment(reference.fragment)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ struct RenderContentCompiler: MarkupVisitor {
}

mutating func visitHeading(_ heading: Heading) -> [RenderContent] {
return [RenderBlockContent.heading(.init(level: heading.level, text: heading.plainText, anchor: urlReadableFragment(heading.plainText)))]
return [RenderBlockContent.heading(.init(level: heading.level, text: heading.plainText, anchor: urlReadableFragment(heading.plainText).addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed)))]
}

mutating func visitListItem(_ listItem: ListItem) -> [RenderContent] {
Expand Down
20 changes: 20 additions & 0 deletions Tests/SwiftDocCTests/Model/RenderContentMetadataTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -297,4 +297,24 @@ class RenderContentMetadataTests: XCTestCase {
default: XCTFail("Unexpected element")
}
}

func testHeadingAnchorShouldBeEncoded() throws {
let (bundle, context) = try testBundleAndContext(named: "TestBundle")
var renderContentCompiler = RenderContentCompiler(context: context, bundle: bundle, identifier: ResolvedTopicReference(bundleIdentifier: bundle.identifier, path: "/path", fragment: nil, sourceLanguage: .swift))

let source = """
## テスト
"""
let document = Document(parsing: source)

let result = try XCTUnwrap(renderContentCompiler.visit(document.child(at: 0)!))
let element = try XCTUnwrap(result.first as? RenderBlockContent)
switch element {
case .heading(let heading):
XCTAssertEqual(heading.level, 2)
XCTAssertEqual(heading.text, "テスト")
XCTAssertEqual(heading.anchor, "%E3%83%86%E3%82%B9%E3%83%88", "The UTF-8 representation of テスト is E3 83 86 E3 82 B9 E3 83 88")
default: XCTFail("Unexpected element")
}
}
}
63 changes: 63 additions & 0 deletions Tests/SwiftDocCTests/Rendering/HeadingAnchorTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
This source file is part of the Swift.org open source project
Copyright (c) 2024 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
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

import Foundation
import XCTest
@testable import SwiftDocC
import SwiftDocCTestUtilities

class HeadingAnchorTests: XCTestCase {
func testEncodeHeadingAnchor() throws {
let catalogURL = try createTempFolder(content: [
Folder(name: "unit-test.docc", content: [
TextFile(name: "Root.md", utf8Content: """
# My root page
This single article defines two headings and links to them
@Metadata {
@TechnologyRoot
}
### テスト
- <doc:#テスト>
### Some heading
- <doc:#Some-heading>
"""),
])
])
let (_, bundle, context) = try loadBundle(from: catalogURL)

let reference = try XCTUnwrap(context.soleRootModuleReference)
let node = try context.entity(with: reference)
let renderContext = RenderContext(documentationContext: context, bundle: bundle)
let converter = DocumentationContextConverter(bundle: bundle, context: context, renderContext: renderContext)
let renderNode = try XCTUnwrap(converter.renderNode(for: node, at: nil))

// Check heading anchors are encoded
let contentSection = try XCTUnwrap(renderNode.primaryContentSections.first as? ContentRenderSection)
let headings: [RenderBlockContent.Heading] = contentSection.content.compactMap {
if case .heading(let heading) = $0 {
return heading
} else {
return nil
}
}
XCTAssertEqual(headings[0].anchor, "%E3%83%86%E3%82%B9%E3%83%88")
XCTAssertEqual(headings[1].anchor, "Some-heading")

// Check links to them
let testTopic0 = try XCTUnwrap(renderNode.references["doc://unit-test/documentation/Root#%E3%83%86%E3%82%B9%E3%83%88"] as? TopicRenderReference)
XCTAssertEqual(testTopic0.url, "/documentation/root#%E3%83%86%E3%82%B9%E3%83%88")
let testTopic1 = try XCTUnwrap(renderNode.references["doc://unit-test/documentation/Root#Some-heading"] as? TopicRenderReference)
XCTAssertEqual(testTopic1.url, "/documentation/root#Some-heading")
}
}

0 comments on commit 6a47d16

Please sign in to comment.