david-swift fd29eccd68
Some checks are pending
Deploy Docs / publish (push) Waiting to run
SwiftLint / SwiftLint (push) Waiting to run
Improve autogenerated docs
2025-10-30 20:48:37 +01:00

164 lines
6.0 KiB
Swift
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// String.swift
// Adwaita
//
// Created by david-swift on 14.01.24.
//
extension String: @retroactive CodingKey {
/// The string.
public var stringValue: String {
self
}
/// A string cannot be represented as an integer.
public var intValue: Int? {
nil
}
/// Initialize from an int value.
/// - Parameter intValue: The int value.
public init?(intValue: Int) {
nil
}
/// Initialize from a string value.
/// - Parameter stringValue: The string value.
public init?(stringValue: String) {
self = stringValue
}
/// Generate a doc comment out of the string.
/// - Parameters:
/// - configuration: The generation configuration.
/// - indent: Indentation added at the beginning of every line.
/// - Returns: The comment.
func docComment(configuration: GenerationConfiguration, indent: String = "") -> String {
applyDocRegex(configuration: configuration)
.split(separator: "\n", omittingEmptySubsequences: false)
.map { $0.trimmingCharacters(in: .whitespaces) }
.enumerated()
.map { $0.offset == 0 ? $0.element.prefix(1).capitalized + $0.element.dropFirst() : $0.element }
.map { "\(indent)/// \($0)" }
.joined(separator: "\n")
}
/// Convert delimited to camel casing.
/// - Parameters:
/// - delimiter: The demiliter.
/// - unshorten: Whether to unshorten.
/// - configuration: The generation configuration.
/// - Returns: The string using camel casing.
func convertDelimitedCasingToCamel(
delimiter: Character,
configuration: GenerationConfiguration,
unshorten: Bool = false
) -> String {
var parts = split(separator: delimiter).map(String.init)
for (index, part) in parts.enumerated() {
if let replacement = configuration.unshorteningMap[part] {
parts[index] = replacement
}
}
let first = parts.removeFirst()
return first + parts.map(\.capitalized).joined()
}
/// Convert a C type to its Swift equivalent using the generation configuration.
/// - Parameter configuration: The generation configuration.
/// - Returns: The Swift type.
func convertCType(configuration: GenerationConfiguration) -> String {
if let replacement = configuration.cTypeReplacements[self] {
return replacement
}
var type = self
if type.last == "*" {
let pointeeType = String(type.dropLast()).convertCType(configuration: configuration)
type = "UnsafeMutablePointer<\(pointeeType)>!"
}
return type
}
/// Apply the documentation regex.
/// - Parameter configuration: The generation configuration.
/// - Returns: The documentation with the regex applied.
func applyDocRegex(configuration: GenerationConfiguration) -> String {
var modified = self
do {
modified = try modified.applyExtraContentRegex()
modified = try modified.applySimpleRegex()
modified = try modified.applyPropertyRegex(configuration: configuration)
modified = try modified.applyBooleanRegex()
modified = try modified.applyHTMLRegex()
modified = try modified.applyNoteRegex()
return modified
} catch {
print("FAIL!")
return modified
}
}
/// Apply the regex to remove additional documentation content.
/// - Returns: The documentation with the regex applied.
func applyExtraContentRegex() throws -> String {
let extraContent = try Regex("##?(.|\\n)*")
return replacing(extraContent, with: "")
}
/// Translate simple definitions into Markdown inline code.
/// - Returns: The documentation with the regex applied.
func applySimpleRegex() throws -> String {
let regex = try Regex("\\[(class|func|method|ctor|signal|const|iface)@(.*?)\\]")
return replacing(regex) { match in
"`\(match.output[2].substring ?? "")`"
}
}
/// Translate property definitions into Swift references.
/// - Parameter configuration: The generation configuration.
/// - Returns: The documentation with the regex applied.
func applyPropertyRegex(configuration: GenerationConfiguration) throws -> String {
let property = try Regex("\\[property@(.*?)\\:(.*?)\\]")
return replacing(property) { match in
let method = String(match.output[2].substring ?? "")
.convertDelimitedCasingToCamel(delimiter: "-", configuration: configuration, unshorten: true)
return "``\(method)(_:)``"
}
}
/// Translate booleans into inline Markdown code with Swift booleans.
/// - Returns: The documentation with the regex applied.
func applyBooleanRegex() throws -> String {
var modified = self
let `false` = try Regex("(`|%)FALSE`?")
modified = modified.replacing(`false`, with: "`false`")
let `true` = try Regex("(`|%)TRUE`?")
modified = modified.replacing(`true`, with: "`true`")
return modified
}
/// Remove broken HTML tags.
/// - Returns: The documentation with the regex applied.
func applyHTMLRegex() throws -> String {
let picture = try Regex("<picture>.*?</picture>")
return replacing(picture, with: "")
}
/// Interpret note/warning blocks.
/// - Returns: The documentation with the regex applied.
func applyNoteRegex() throws -> String {
var modified = self
let note = try Regex("::: note\\n((.|\\n)*?)(\\n\\n)?")
modified = modified.replacing(note) { match in
"> [!NOTE]\n> \(match.output[1].substring ?? "")"
}
let warning = try Regex("::: warning\\n((.|\\n)*?)(\\n\\n)?")
modified = modified.replacing(warning) { match in
"> [!WARNING]\n> \(match.output[1].substring ?? "")"
}
return modified
}
}