Skip to content

Add support for @Small directive #380

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ extension RenderBlockContent: TextIndexing {
return row.columns.map { column in
return column.content.rawIndexableTextContent(references: references)
}.joined(separator: " ")
case .small(let small):
return small.inlineContent.rawIndexableTextContent(references: references)
default:
fatalError("unknown RenderBlockContent case in rawIndexableTextContent")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ public enum RenderBlockContent: Equatable {
/// A table that contains a list of row data.
case table(Table)

/// A row in a grid-based layout system that describes a collection of columns.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mega nit, this probably belongs in another patch.

Copy link
Contributor Author

@ethan-kusters ethan-kusters Sep 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah agreed- I just missed it in #378 so I thought it was worth cleaning up here. I can split it into a separate commit though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would be nice

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split out here: e56bd43

case row(Row)

/// A paragraph of small print content that should be rendered in a small font.
case small(Small)

// Warning: If you add a new case to this enum, make sure to handle it in the Codable
// conformance at the bottom of this file, and in the `rawIndexableTextContent` method in
Expand Down Expand Up @@ -427,6 +431,15 @@ public enum RenderBlockContent: Equatable {
public let content: [RenderBlockContent]
}
}

/// A paragraph of small print content that should be rendered in a small font.
///
/// Small is based on HTML's `<small>` tag and could contain content like legal,
/// license, or copyright text.
public struct Small: Codable, Equatable {
/// The inline content that should be rendered.
public let inlineContent: [RenderInlineContent]
}
}

// Codable conformance
Expand Down Expand Up @@ -489,11 +502,15 @@ extension RenderBlockContent: Codable {
columns: container.decode([Row.Column].self, forKey: .columns)
)
)
case .small:
self = try .small(
Small(inlineContent: container.decode([RenderInlineContent].self, forKey: .inlineContent))
)
}
}

private enum BlockType: String, Codable {
case paragraph, aside, codeListing, heading, orderedList, unorderedList, step, endpointExample, dictionaryExample, table, termList, row
case paragraph, aside, codeListing, heading, orderedList, unorderedList, step, endpointExample, dictionaryExample, table, termList, row, small
}

private var type: BlockType {
Expand All @@ -510,6 +527,7 @@ extension RenderBlockContent: Codable {
case .table: return .table
case .termList: return .termList
case .row: return .row
case .small: return .small
default: fatalError("unknown RenderBlockContent case in type property")
}
}
Expand Down Expand Up @@ -559,6 +577,8 @@ extension RenderBlockContent: Codable {
case .row(let row):
try container.encode(row.numberOfColumns, forKey: .numberOfColumns)
try container.encode(row.columns, forKey: .columns)
case .small(let small):
try container.encode(small.inlineContent, forKey: .inlineContent)
default:
fatalError("unknown RenderBlockContent case in encode method")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ struct DirectiveIndex {
DeprecationSummary.self,
Row.self,
Options.self,
Small.self,
]

private static let topLevelTutorialDirectives: [AutomaticDirectiveConvertible.Type] = [
Expand Down
80 changes: 80 additions & 0 deletions Sources/SwiftDocC/Semantics/Reference/Small.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
This source file is part of the Swift.org open source project

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
See https://swift.org/CONTRIBUTORS.txt for Swift project authors
*/

import Foundation
import Markdown

/// A directive for specifying small print text like legal, license, or copyright text that
/// should be rendered in a smaller font size.
///
/// The `@Small` directive is based on HTML's small tag (`<small>`). It supports any inline markup
/// formatting like bold and italics but does not support more structured markup like ``Row``
/// and ``Row/Column``.
///
/// ```md
/// You can create a sloth using the ``init(name:color:power:)``
/// initializer, or create randomly generated sloth using a
/// ``SlothGenerator``:
///
/// let slothGenerator = MySlothGenerator(seed: randomSeed())
/// let habitat = Habitat(isHumid: false, isWarm: true)
///
/// // ...
///
/// @Small {
/// _Licensed under Apache License v2.0 with Runtime Library Exception._
/// }
/// ```
public final class Small: Semantic, AutomaticDirectiveConvertible, MarkupContaining {
public let originalMarkup: BlockDirective

/// The inline markup that should be rendered in a small font.
@ChildMarkup(numberOfParagraphs: .oneOrMore)
public private(set) var content: MarkupContainer

static var keyPaths: [String : AnyKeyPath] = [
"content" : \Small._content,
]

override var children: [Semantic] {
return [content]
}

var childMarkup: [Markup] {
return content.elements
}

@available(*, deprecated,
message: "Do not call directly. Required for 'AutomaticDirectiveConvertible'."
)
init(originalMarkup: BlockDirective) {
self.originalMarkup = originalMarkup
}
}

extension Small: RenderableDirectiveConvertible {
func render(with contentCompiler: inout RenderContentCompiler) -> [RenderContent] {
// Render the content normally
let renderBlockContent = content.elements.flatMap { markupElement in
return contentCompiler.visit(markupElement) as! [RenderBlockContent]
}

// Transform every paragraph in the render block content to a small paragraph
let transformedRenderBlockContent = renderBlockContent.map { block -> RenderBlockContent in
guard case let .paragraph(paragraph) = block else {
return block
}

return .small(RenderBlockContent.Small(inlineContent: paragraph.inlineContent))
}

return transformedRenderBlockContent
}
}
22 changes: 22 additions & 0 deletions Sources/SwiftDocC/SwiftDocC.docc/Resources/RenderNode.spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,9 @@
{
"$ref": "#/components/schemas/Aside"
},
{
"$ref": "#/components/schemas/Small"
},
{
"$ref": "#/components/schemas/Heading"
},
Expand Down Expand Up @@ -619,6 +622,25 @@
}
}
},
"Small": {
"type": "object",
"required": [
"type",
"inlineContent"
],
"properties": {
"type": {
"type": "string",
"enum": ["small"]
},
"inlineContent": {
"type": "array",
"items": {
"$ref": "#/components/schemas/RenderInlineContent"
}
}
}
},
"Heading": {
"type": "object",
"required": [
Expand Down
33 changes: 33 additions & 0 deletions Tests/SwiftDocCTests/Rendering/RenderNodeTranslatorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1058,4 +1058,37 @@ class RenderNodeTranslatorTests: XCTestCase {
XCTAssertEqual(row.columns.last?.size, 5)
XCTAssertEqual(row.columns.last?.content.count, 3)
}

func testSmall() throws {
let (bundle, context) = try testBundleAndContext(named: "BookLikeContent")
let reference = ResolvedTopicReference(
bundleIdentifier: bundle.identifier,
path: "/documentation/BestBook/MyArticle",
sourceLanguage: .swift
)
let article = try XCTUnwrap(context.entity(with: reference).semantic as? Article)
var translator = RenderNodeTranslator(
context: context,
bundle: bundle,
identifier: reference,
source: nil
)
let renderNode = try XCTUnwrap(translator.visitArticle(article) as? RenderNode)

let discussion = try XCTUnwrap(
renderNode.primaryContentSections.first(
where: { $0.kind == .content }
) as? ContentRenderSection
)

guard case let .small(small) = discussion.content.last else {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we not have a separate test from row and column one for this? I find that having smaller test cases helps pin out failures faster.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah good catch- I meant to create a new one here. Should be fixed now. Thanks!

XCTFail("Expected to find small as last child.")
return
}

XCTAssertEqual(
small.inlineContent,
[.text("Copyright (c) 2022 Apple Inc and the Swift Project authors. All Rights Reserved.")]
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class DirectiveIndexTests: XCTestCase {
"Options",
"Redirected",
"Row",
"Small",
"Snippet",
"Stack",
"TechnologyRoot",
Expand All @@ -50,6 +51,7 @@ class DirectiveIndexTests: XCTestCase {
DirectiveIndex.shared.renderableDirectives.keys.sorted(),
[
"Row",
"Small",
]
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ class RowTests: XCTestCase {
["1: warning – org.swift.docc.HasAtLeastOne<Row, Column>"]
)

XCTAssertEqual(renderBlockContent.count, 1)
XCTAssertEqual(
renderBlockContent,
renderBlockContent.first,
Comment on lines +32 to +34
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this not be in a separate patch?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split into a separate commit here: e4a6fc4.

.row(.init(numberOfColumns: 0, columns: []))
)
}
Expand Down Expand Up @@ -65,8 +66,9 @@ class RowTests: XCTestCase {
]
)

XCTAssertEqual(renderBlockContent.count, 1)
XCTAssertEqual(
renderBlockContent,
renderBlockContent.first,
.row(RenderBlockContent.Row(
numberOfColumns: 6,
columns: [
Expand Down Expand Up @@ -129,8 +131,9 @@ class RowTests: XCTestCase {
]
)

XCTAssertEqual(renderBlockContent.count, 1)
XCTAssertEqual(
renderBlockContent,
renderBlockContent.first,
.row(RenderBlockContent.Row(
numberOfColumns: 0,
columns: []
Expand Down Expand Up @@ -159,8 +162,9 @@ class RowTests: XCTestCase {
]
)

XCTAssertEqual(renderBlockContent.count, 1)
XCTAssertEqual(
renderBlockContent,
renderBlockContent.first,
.row(RenderBlockContent.Row(
numberOfColumns: 1,
columns: [
Expand All @@ -187,8 +191,9 @@ class RowTests: XCTestCase {
]
)

XCTAssertEqual(renderBlockContent.count, 1)
XCTAssertEqual(
renderBlockContent,
renderBlockContent.first,
.row(RenderBlockContent.Row(numberOfColumns: 0, columns: []))
)
}
Expand All @@ -212,8 +217,9 @@ class RowTests: XCTestCase {
XCTAssertNotNil(row)
XCTAssertEqual(problems, [])

XCTAssertEqual(renderBlockContent.count, 1)
XCTAssertEqual(
renderBlockContent,
renderBlockContent.first,
.row(RenderBlockContent.Row(
numberOfColumns: 5,
columns: [
Expand Down Expand Up @@ -252,8 +258,9 @@ class RowTests: XCTestCase {
XCTAssertNotNil(row)
XCTAssertEqual(problems, [])

XCTAssertEqual(renderBlockContent.count, 1)
XCTAssertEqual(
renderBlockContent,
renderBlockContent.first,
.row(RenderBlockContent.Row(
numberOfColumns: 1,
columns: [
Expand Down
Loading