Skip to content

Commit

Permalink
✨ feat: support descriptive texts (header, title, legend, caption, fo…
Browse files Browse the repository at this point in the history
…oter) (#62)

* ✨ feat: support descriptive texts (header, title, legend, caption, footer) (closes #61)

closes #61

* ♻️ refactor: scheme for better auto-completion
  • Loading branch information
MarcoEidinger committed Jan 27, 2023
1 parent 08ba6cd commit cbeabf0
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 2 deletions.
8 changes: 8 additions & 0 deletions Configuration/Examples/Rich/.swiftplantuml.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,11 @@ stereotypes:
spot:
character: P
color: AntiqueWhite
texts:
header: Simple header example
title: |
<u>Formatted</u> title example
on <i>several</i> lines and using <font color=red>html</font>
legend: Some boxed text
caption: Second to last
footer: The end
42 changes: 42 additions & 0 deletions Configuration/Schema/json-schema-swiftplantuml.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@
"color": "AntiqueWhite"
}
}
},
"texts": {
"title": "Diagram Title"
}
}],
"definitions": {
Expand Down Expand Up @@ -1023,6 +1026,45 @@
}
},
"additionalProperties": true
},
"texts": {
"$id": "#/properties/texts",
"type": "object",
"title": "The texts schema",
"description": "Descriptive texts (a.k.a common commands) you can add around your diagram",
"default": {},
"examples": [{
"title": "Diagram Title"
}],
"required": [],
"properties": {
"header": {
"type": "string",
"title": "The header Schema",
"description": "Add a header to the top right above the diagram"
},
"title": {
"type": "string",
"title": "The title Schema",
"description": "Add a title above the diagram"
},
"legend": {
"type": "string",
"title": "The legend Schema",
"description": "Add a legend (boxed text) under the diagram but above the caption"
},
"caption": {
"type": "string",
"title": "The caption Schema",
"description": "Add a caption under the diagram"
},
"footer": {
"type": "string",
"title": "The footer Schema",
"description": "Add a footer at the bottom below the diagram"
}
},
"additionalProperties": true
}
},
"additionalProperties": true
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ elements:
showNestedTypes: false
showExtensions: merged
theme: plain # see https://plantuml.com/theme
texts:
title: |
<u>Formatted</u> title example
on <i>several</i> lines and using <font color=red>html</font>
skinparamCommands: # see https://plantuml.com/skinparam
- skinparam classBackgroundColor PaleGreen
- skinparam classArrowColor SeaGreen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public enum AccessLevel: String, Codable {
/// Configuration options to influence the generation and visual representation of the class diagram
public struct Configuration: Codable {
/// memberwise initializer
public init(files: FileOptions = FileOptions(), elements: ElementOptions = ElementOptions(), hideShowCommands: [String]? = ["hide empty members"], skinparamCommands: [String]? = ["skinparam shadowing false"], includeRemoteURL: String? = nil, theme: Theme? = nil, relationships: RelationshipOptions = RelationshipOptions(), stereotypes: Stereotypes = Stereotypes.default, relationshipExclude _: [String]? = nil) {
public init(files: FileOptions = FileOptions(), elements: ElementOptions = ElementOptions(), hideShowCommands: [String]? = ["hide empty members"], skinparamCommands: [String]? = ["skinparam shadowing false"], includeRemoteURL: String? = nil, theme: Theme? = nil, relationships: RelationshipOptions = RelationshipOptions(), stereotypes: Stereotypes = Stereotypes.default, relationshipExclude _: [String]? = nil, texts: PageTexts? = nil) {
self.files = files
self.elements = elements
self.hideShowCommands = hideShowCommands
Expand All @@ -27,6 +27,7 @@ public struct Configuration: Codable {
self.theme = theme
self.relationships = relationships
self.stereotypes = stereotypes
self.texts = texts
}

public init(from decoder: Decoder) throws {
Expand Down Expand Up @@ -55,6 +56,9 @@ public struct Configuration: Codable {
if let stereotypes = try container.decodeIfPresent(Stereotypes.self, forKey: .stereotypes) {
self.stereotypes = stereotypes
}
if let texts = try container.decodeIfPresent(PageTexts.self, forKey: .texts) {
self.texts = texts
}
}

/// default configuration used if no configuration file was found
Expand Down Expand Up @@ -83,6 +87,9 @@ public struct Configuration: Codable {
/// sterotypes (spotted character with background color and optional name) to be shown for an entity type
public private(set) var stereotypes = Stereotypes(classStereotype: Stereotype.class, structStereotype: Stereotype.struct, extensionStereotype: Stereotype.extension, enumStereotype: Stereotype.enum, protocolStereotype: Stereotype.protocol)

// Descriptive texts ("common commands") you can add around your diagram
public var texts: PageTexts?

internal var shallExtensionsBeMerged: Bool {
elements.showExtensions.safelyUnwrap == .merged
}
Expand Down
62 changes: 62 additions & 0 deletions Sources/SwiftPlantUMLFramework/Configuration/PageTexts.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import Foundation
/// Descriptive texts ("common commands") you can add around your diagram
public struct PageTexts: Codable {
internal init(header: String? = nil, title: String? = nil, legend: String? = nil, caption: String? = nil, footer: String? = nil) {
self.header = header
self.title = title
self.legend = legend
self.caption = caption
self.footer = footer
}

/// add a header to the top right above the diagram
public var header: String?
/// add a title above the diagram
public var title: String?
/// add a legend (boxed text) under the diagram but above the caption
public var legend: String?
/// add a caption under the diagram
public var caption: String?
/// add a footer at the bottom below the diagram
public var footer: String?
}

extension PageTexts {
func plantuml() -> String? {
if header == nil,
title == nil,
legend == nil,
caption == nil,
footer == nil
{
return nil
}
var text = ""
if let header = header {
text.appendAsNewLine("header")
text.appendAsNewLine(header)
text.appendAsNewLine("end header")
}
if let title = title {
text.appendAsNewLine("title")
text.appendAsNewLine(title)
text.appendAsNewLine("end title")
}
if let legend = legend {
text.appendAsNewLine("legend")
text.appendAsNewLine(legend)
text.appendAsNewLine("end legend")
}
if let caption = caption {
text.appendAsNewLine("caption")
text.appendAsNewLine(caption)
text.appendAsNewLine("end caption")
}
if let footer = footer {
text.appendAsNewLine("footer")
text.appendAsNewLine(footer)
text.appendAsNewLine("end footer")
}
return text
}
}
4 changes: 4 additions & 0 deletions Sources/SwiftPlantUMLFramework/PlantUMLScript.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public struct PlantUMLScript {
}
text.appendAsNewLine(defaultStyling)

if let texts = configuration.texts?.plantuml() {
text.appendAsNewLine(texts)
}

let newLine = "\n"
var mainContent = newLine

Expand Down
109 changes: 109 additions & 0 deletions Tests/SwiftPlantUMLFrameworkTests/PageTextsTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
@testable import SwiftPlantUMLFramework
import XCTest

final class PageTextsTests: XCTestCase {
func testNone() throws {
let texts = PageTexts()
XCTAssertNil(texts.plantuml())
}

func testHeader() throws {
let headerText = """
<u>Simple</u> header example
on <i>several</i> lines and using <font color=red>html</font>
"""

let texts = PageTexts(header: headerText)
let result = texts.plantuml()

let expected = """
header
\(headerText)
end header
"""
XCTAssertEqual(result, expected)
}

func testTitle() throws {
let titleText = """
<u>Simple</u> title example
on <i>several</i> lines and using <font color=red>html</font>
"""

let texts = PageTexts(title: titleText)
let result = texts.plantuml()

let expected = """
title
\(titleText)
end title
"""
XCTAssertEqual(result, expected)
}

func testLegend() throws {
let legendText = """
<u>Simple</u> legend example
on <i>several</i> lines and using <font color=red>html</font>
"""

let texts = PageTexts(legend: legendText)
let result = texts.plantuml()

let expected = """
legend
\(legendText)
end legend
"""
XCTAssertEqual(result, expected)
}

func testCaption() throws {
let captionText = """
<u>Simple</u> caption example
on <i>several</i> lines and using <font color=red>html</font>
"""

let texts = PageTexts(caption: captionText)
let result = texts.plantuml()

let expected = """
caption
\(captionText)
end caption
"""
XCTAssertEqual(result, expected)
}

func testFooter() throws {
let footerText = """
<u>Simple</u> footer example
on <i>several</i> lines and using <font color=red>html</font>
"""

let texts = PageTexts(footer: footerText)
let result = texts.plantuml()

let expected = """
footer
\(footerText)
end footer
"""
XCTAssertEqual(result, expected)
}

func testAll() throws {
let texts = PageTexts(header: "1", title: "2", legend: "3", caption: "4", footer: "5")
let result = try XCTUnwrap(texts.plantuml())
XCTAssertTrue(result.contains("1"))
XCTAssertTrue(result.contains("2"))
XCTAssertTrue(result.contains("3"))
XCTAssertTrue(result.contains("4"))
XCTAssertTrue(result.contains("5"))
}
}
9 changes: 9 additions & 0 deletions Tests/SwiftPlantUMLFrameworkTests/PlantUMLScriptTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ final class PlantUMLScriptTests: XCTestCase {
XCTAssertEqual(script.text.noSpacesAndNoLineBreaks, expected.noSpacesAndNoLineBreaks)
}

func testIncludingPageTexts() {
guard let items = try! SyntaxStructure.create(from: getTestFile())?.substructure else { return XCTFail("cannot read test data") }
let headerText = "Header123"
var config = Configuration.default
config.texts = PageTexts(header: headerText)
let script = PlantUMLScript(items: items, configuration: config)
XCTAssertTrue(script.text.contains(headerText))
}

func getTestFile(named: String = "basics") throws -> URL {
// https://stackoverflow.com/questions/47177036/use-resources-in-unit-tests-with-swift-package-manager
let path = Bundle.module.path(forResource: named, ofType: "txt", inDirectory: "TestData") ?? "nonesense"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,9 @@ stereotypes:
spot:
character: P
color: AntiqueWhite

texts:
header: headerText
title: titleText
legend: legendText
caption: captionText
footer: footerText

0 comments on commit cbeabf0

Please sign in to comment.