Skip to content

Commit

Permalink
Themes (#168)
Browse files Browse the repository at this point in the history
* Add dynamic color extension

* Add a basic theme

* Add DocC theme

* Fix block spacing logic

* Update theme initializer

* Add DocC theme tests

* Add GitHub theme
  • Loading branch information
gonzalezreal authored Dec 12, 2022
1 parent 0838208 commit c91729d
Show file tree
Hide file tree
Showing 52 changed files with 976 additions and 310 deletions.
41 changes: 41 additions & 0 deletions Sources/MarkdownUI/Common/Color+RGBA.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import SwiftUI

extension Color {
public init(rgba: UInt32) {
self.init(
red: CGFloat((rgba & 0xff00_0000) >> 24) / 255.0,
green: CGFloat((rgba & 0x00ff_0000) >> 16) / 255.0,
blue: CGFloat((rgba & 0x0000_ff00) >> 8) / 255.0,
opacity: CGFloat(rgba & 0x0000_00ff) / 255.0
)
}

public init(light: @escaping @autoclosure () -> Color, dark: @escaping @autoclosure () -> Color) {
#if os(macOS)
self.init(
nsColor: .init(name: nil) { appearance in
if appearance.bestMatch(from: [.aqua, .darkAqua]) == .aqua {
return NSColor(light())
} else {
return NSColor(dark())
}
}
)
#elseif os(iOS) || os(tvOS)
self.init(
uiColor: .init { traitCollection in
switch traitCollection.userInterfaceStyle {
case .unspecified, .light:
return UIColor(light())
case .dark:
return UIColor(dark())
@unknown default:
return UIColor(light())
}
}
)
#elseif os(watchOS)
self.init(uiColor: dark())
#endif
}
}
26 changes: 25 additions & 1 deletion Sources/MarkdownUI/Common/Size.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,16 @@ extension Size {
}

extension View {
public func frame(
width: Size? = nil,
height: Size? = nil,
alignment: Alignment = .center
) -> some View {
self.modifier(FrameModifier(width: width, height: height, alignment: alignment))
}

public func frame(minWidth: Size, alignment: Alignment = .center) -> some View {
self.modifier(FrameModifier(minWidth: minWidth, alignment: alignment))
self.modifier(FrameModifier2(minWidth: minWidth, alignment: alignment))
}

public func padding(_ edges: Edge.Set = .all, _ length: Size) -> some View {
Expand All @@ -55,6 +63,22 @@ extension View {
private struct FrameModifier: ViewModifier {
@Environment(\.fontStyle) private var fontStyle

let width: Size?
let height: Size?
let alignment: Alignment

func body(content: Content) -> some View {
content.frame(
width: self.width?.points(relativeTo: self.fontStyle),
height: self.height?.points(relativeTo: self.fontStyle),
alignment: self.alignment
)
}
}

private struct FrameModifier2: ViewModifier {
@Environment(\.fontStyle) private var fontStyle

let minWidth: Size
let alignment: Alignment

Expand Down
87 changes: 2 additions & 85 deletions Sources/MarkdownUI/Theme/Styles/BlockStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,90 +19,7 @@ public struct BlockStyle {
}

extension BlockStyle {
public static var defaultImage: BlockStyle {
self.default
}

public static func defaultImage(alignment: HorizontalAlignment) -> BlockStyle {
BlockStyle { label in
ZStack {
label
}
.frame(maxWidth: .infinity, alignment: .init(horizontal: alignment, vertical: .center))
}
}

public static var `default`: BlockStyle {
BlockStyle { label in
label
.lineSpacing(.em(0.15))
}
}

public static var defaultBlockquote: BlockStyle {
BlockStyle { label in
label
.markdownFontStyle {
$0.italic()
}
.padding(.leading, .em(2))
.padding(.trailing, .em(1))
}
}

public static var defaultCodeBlock: BlockStyle {
BlockStyle { label in
label.markdownFontStyle {
$0.monospaced()
}
.padding(.leading, .em(1))
.lineSpacing(.em(0.15))
}
}

public static var defaultHeading1: BlockStyle {
defaultHeading(level: 1)
}

public static var defaultHeading2: BlockStyle {
defaultHeading(level: 2)
}

public static var defaultHeading3: BlockStyle {
defaultHeading(level: 3)
}

public static var defaultHeading4: BlockStyle {
defaultHeading(level: 4)
}

public static var defaultHeading5: BlockStyle {
defaultHeading(level: 5)
}

public static var defaultHeading6: BlockStyle {
defaultHeading(level: 6)
}

private static func defaultHeading(level: Int) -> BlockStyle {
BlockStyle { label in
label.markdownFontStyle {
$0.bold()
.size(headingSizes[level - 1])
}
.markdownBlockSpacing(top: .rem(1.5))
}
}

public static var defaultThematicBreak: BlockStyle {
BlockStyle { _ in
Divider()
.markdownBlockSpacing(top: .rem(2), bottom: .rem(2))
}
public static var unit: BlockStyle {
BlockStyle { $0 }
}
}

private let headingSizes: [Size] = [
.em(2), .em(1.5), .em(1.17),
.em(1), .em(0.83), .em(0.67),
]
2 changes: 1 addition & 1 deletion Sources/MarkdownUI/Theme/Styles/FontStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ extension FontStyle: Hashable {
}

extension FontStyle {
public static var `default`: FontStyle {
public static var body: FontStyle {
#if os(macOS)
return .system(size: 13)
#elseif os(iOS)
Expand Down
38 changes: 10 additions & 28 deletions Sources/MarkdownUI/Theme/Styles/InlineStyle.swift
Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
import SwiftUI

public struct InlineStyle {
var update: (inout AttributeContainer) -> Void
var transform: (inout AttributeContainer) -> Void

public init(update: @escaping (inout AttributeContainer) -> Void) {
self.update = update
public init(transform: @escaping (_ attributes: inout AttributeContainer) -> Void) {
self.transform = transform
}

func updating(_ attributes: AttributeContainer) -> AttributeContainer {
func transforming(_ attributes: AttributeContainer) -> AttributeContainer {
var newAttributes = attributes
update(&newAttributes)
transform(&newAttributes)
return newAttributes
}
}

extension InlineStyle {
public static var `default`: Self {
public static var unit: Self {
.init { _ in }
}

public static var monospaced: Self {
.monospaced()
}

public static func monospaced(backgroundColor: Color? = nil) -> Self {
public static func monospaced(size: Size = .em(1), backgroundColor: Color? = nil) -> Self {
.init { attributes in
attributes.fontStyle = attributes.fontStyle?.monospaced()
attributes.fontStyle = attributes.fontStyle?.monospaced().size(size)
attributes.backgroundColor = backgroundColor
}
}
Expand All @@ -36,13 +32,6 @@ extension InlineStyle {
}
}

public static var italicUnderline: Self {
.init { attributes in
attributes.fontStyle = attributes.fontStyle?.italic()
attributes.underlineStyle = .single
}
}

public static var bold: Self {
.init { attributes in
attributes.fontStyle = attributes.fontStyle?.bold()
Expand All @@ -61,16 +50,9 @@ extension InlineStyle {
}
}

public static var redacted: Self {
.init { attributes in
attributes.foregroundColor = .primary
attributes.backgroundColor = .primary
}
}

public static var underlineDot: Self {
public static func foregroundColor(_ color: Color) -> Self {
.init { attributes in
attributes.underlineStyle = .init(pattern: .dot)
attributes.foregroundColor = color
}
}
}
23 changes: 5 additions & 18 deletions Sources/MarkdownUI/Theme/Styles/ListMarkerStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,40 +81,27 @@ extension ListMarkerStyle where Configuration == ListItemConfiguration {
}
}

private struct Bullet: View {
public struct Bullet: View {
@Environment(\.fontStyle.size) private var fontSize
private let image: SwiftUI.Image

var body: some View {
public var body: some View {
image.font(.system(size: round(fontSize / 3)))
}

static var disc: Bullet {
public static var disc: Bullet {
.init(image: .init(systemName: "circle.fill"))
}

static var circle: Bullet {
public static var circle: Bullet {
.init(image: .init(systemName: "circle"))
}

static var square: Bullet {
public static var square: Bullet {
.init(image: .init(systemName: "square.fill"))
}
}

public struct TaskListItemConfiguration {
public var isCompleted: Bool
}

extension ListMarkerStyle where Configuration == TaskListItemConfiguration {
// MARK: - Tasks

public static var checkmarkSquareFill: ListMarkerStyle {
ListMarkerStyle { configuration in
SwiftUI.Image(systemName: configuration.isCompleted ? "checkmark.square.fill" : "square")
.symbolRenderingMode(.hierarchical)
.imageScale(.small)
.frame(minWidth: .em(1.5), alignment: .trailing)
}
}
}
16 changes: 5 additions & 11 deletions Sources/MarkdownUI/Theme/Styles/TableBorderStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,16 @@ import SwiftUI

public struct TableBorderStyle {
let border: TableBorder
let style: AnyShapeStyle
let color: Color
let strokeStyle: StrokeStyle

public init<S: ShapeStyle>(_ border: TableBorder = .all, style: S, strokeStyle: StrokeStyle) {
public init(_ border: TableBorder = .all, color: Color, strokeStyle: StrokeStyle) {
self.border = border
self.style = .init(style)
self.color = color
self.strokeStyle = strokeStyle
}

public init<S: ShapeStyle>(_ border: TableBorder = .all, style: S, width: CGFloat = 1) {
self.init(border, style: style, strokeStyle: .init(lineWidth: width))
}
}

extension TableBorderStyle {
public static var `default`: TableBorderStyle {
.init(style: Color.secondary)
public init(_ border: TableBorder = .all, color: Color, width: CGFloat = 1) {
self.init(border, color: color, strokeStyle: .init(lineWidth: width))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public struct TableCellBackgroundStyle {
}

extension TableCellBackgroundStyle {
public static var `default`: TableCellBackgroundStyle {
public static var clear: TableCellBackgroundStyle {
TableCellBackgroundStyle { _ in
Color.clear
}
Expand Down
13 changes: 0 additions & 13 deletions Sources/MarkdownUI/Theme/Styles/TableCellStyle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,3 @@ public struct TableCellStyle {
self.makeBody = { AnyView(makeBody($0)) }
}
}

extension TableCellStyle {
public static var `default`: TableCellStyle {
TableCellStyle { configuration in
configuration.label
.markdownFontStyle { fontStyle in
configuration.row == 0 ? fontStyle.bold() : fontStyle
}
.padding(.horizontal, .em(0.72))
.padding(.vertical, .em(0.35))
}
}
}
Loading

0 comments on commit c91729d

Please sign in to comment.