Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
134 commits
Select commit Hold shift + click to select a range
6e4dd73
Add ability to include navigation bar items outside of the collapsibl…
Apr 2, 2025
de6931b
Fix warning.
Apr 2, 2025
e3165b4
Add convenience initializers.
Apr 3, 2025
634933f
Remove initializers—confuses compiler.
Apr 3, 2025
cba9a3c
Improve parameter name.
Apr 10, 2025
aefa671
Fix `Form` rendering inside `NavigationBar`.
Apr 12, 2025
235bee0
Merge remote-tracking branch 'refs/remotes/upstream/main'
Apr 12, 2025
46fd9c3
Merge upstream branches.
Apr 12, 2025
606f3c1
Merge remote-tracking branch 'refs/remotes/upstream/main'
Apr 12, 2025
88a16f0
Decouple `Form` and `SubscribeAction`. Introduce `ControlGroup`. Othe…
Apr 14, 2025
2736b24
Add missing documentation and improve access levels.
Apr 14, 2025
389b3b0
Minor polishes and test fixes.
Apr 14, 2025
93b4014
Extend `FormItem` with core modifiers. Reimplement `SubscribeForm` us…
Apr 14, 2025
7848d3b
Add preliminary site-search with lunr.js.
Apr 15, 2025
22c6793
Polish search result presentation.
Apr 15, 2025
2e14b8f
Add `date` to `SearchResult`. Add missing documentation. Misc. polishes.
Apr 15, 2025
47aaa31
Update `searchResultView` to use `<template>`.
Apr 15, 2025
60ddb0f
Improve `SearchField` sizing.
Apr 15, 2025
e33b2f3
Synchronize search fields on the same page.
Apr 15, 2025
b3c8232
Remove unneeded comments.
Apr 15, 2025
47438af
Refactor search.js.
Apr 15, 2025
9e0b76a
More refactoring.
Apr 15, 2025
fbbfd00
Add styling modifiers to `SearchField`. Other minor UI improvements.
Apr 15, 2025
f4ab53c
Rename `SearchField` to `SearchForm`. Extend search to regular pages.
Apr 15, 2025
860041b
Allow custom view at top of search results.
Apr 15, 2025
44554f1
Hide search bar at top of search results when search form resides in …
Apr 16, 2025
26333de
Add search role to search form.
Apr 16, 2025
3dad84e
Apply tag styling to each individual tag.
Apr 16, 2025
96c7500
Highlight appearances of search term in description.
Apr 16, 2025
b875e3e
Polish search UI.
Apr 16, 2025
6dcfb53
Refactor code.
Apr 16, 2025
ed57bb2
Fix search-result header's changing after secondary search.
Apr 16, 2025
22e278c
Fix clear button flicker.
Apr 16, 2025
69bd624
Remove unneeded comment.
Apr 16, 2025
5af2bc0
Fix broken page path.
Apr 16, 2025
c78db40
Minor refactoring.
Apr 16, 2025
da76140
Polish UI.
Apr 16, 2025
188dec7
Improve `NavigationBar` responsive layout. Misc. UI polishes.
Apr 16, 2025
e565a98
Tidy JS.
Apr 16, 2025
f9a9c05
Improve responsive layout of `NavigationBar`. Make `Spacer` a `Naviga…
Apr 16, 2025
dbee95f
Remove test class.
Apr 16, 2025
b13c300
Improve names.
Apr 16, 2025
c8e9088
Fix tests.
Apr 17, 2025
05e164c
Fix multiline Markdown handling in `Text`.
Apr 17, 2025
5173568
Fix content type.
Apr 17, 2025
8ac1c85
Fix check in `ContainerRelativeFrame`.
Apr 17, 2025
b56f5b2
Fix type safety throughout framework.
Apr 18, 2025
baba5dc
Clean up modifiers.
Apr 18, 2025
431c405
Fix SwiftLint warnings.
Apr 18, 2025
511db58
Fix `border()`.
Apr 18, 2025
008aaed
Clean up modifiers.
Apr 18, 2025
0494059
Simplify type safety.
Apr 18, 2025
cc8c809
Improve names.
Apr 19, 2025
a14b93b
Fix various inits.
Apr 19, 2025
aa0b169
Simplify type safety.
Apr 19, 2025
37e3bef
Fix tests.
Apr 19, 2025
abe7d31
Fix holes in type safety.
Apr 19, 2025
fc7e371
Add modifiers to `Body`.
Apr 19, 2025
c45b8aa
Delete unused code. Fix SwiftLint warnings.
Apr 19, 2025
fddb0a1
Improve type safety, including moving `CustomStringConvertible` to `I…
Apr 21, 2025
1476cd2
Rename `render()` to `markup()`. Improve type safety by having `marku…
Apr 21, 2025
c23c60a
Merge remote-tracking branch 'refs/remotes/upstream/main'
Apr 21, 2025
11f09f8
Add small font styles.
Apr 21, 2025
2688325
Revert unneeded name change.
Apr 21, 2025
414fe46
Add `navigationMenuIcon()` and `navigationMenuStyle()` modifiers to `…
Apr 21, 2025
a9539d9
Fix type safety for `NavigationItem` and `FormItem`. Extend `.hidden(…
Apr 21, 2025
f88e820
Allow custom view when no results available in `SearchForm`.
Apr 21, 2025
64df7db
Improve ergonomics of `ItemAlignment` by defaulting to `.trailing`.
Apr 21, 2025
08fa454
Update version number.
Apr 21, 2025
d882a33
Remove `link` from `SearchResult`.
Apr 21, 2025
e78da20
Refactor `configuredAsNavigationItem()` into `NavigationItemConfigura…
Apr 22, 2025
226dd7f
Fix `Spacer` sizing.
Apr 22, 2025
9e3db58
Fix `Spacer` automatic sizing.
Apr 22, 2025
efa38c9
Drop `NavigationItemConfigurable` from `Spacer`.
Apr 22, 2025
888e95c
Move `isPrimitive` to `BodyElement`.
Apr 22, 2025
575bcc2
Remove `HeadElement` conformance from `Tag`. Create new `DocumentStyl…
Apr 22, 2025
4d535eb
Add missing quotes to font names.
Apr 22, 2025
66ec952
Fix duplicate `@font-face` rules being outputted.
Apr 22, 2025
862de9c
Move priority to `important()` modifier.
Apr 22, 2025
784177c
Rename `DocumentStyle` to `MetaStyle` to match other head elements.
Apr 23, 2025
2808b9c
Remove unneeded `DocumentElement` protocol.
Apr 23, 2025
49ec045
Add `lineLimit()` modifier to `Text`.
Apr 24, 2025
59c1555
Fix bug making area around `LinkGroup` clickable.
Apr 24, 2025
396950d
Fix wrong return value in `lineNumberVisibility()`.
Apr 24, 2025
22eaa59
Add `frame()` to `NavigationItem`.
Apr 24, 2025
69a8c6a
Improve `ColumnWidth`.
Apr 24, 2025
5d0e4f3
Fix `badge()` modifier.
Apr 24, 2025
0be4e89
Update a `Button` initializer to better match SwiftUI. Add an initial…
Apr 24, 2025
7a43ad4
Fix `ListStyle`-related bugs in `List`. Add `.horizontalGroup` style.…
Apr 24, 2025
b714259
Polish internal views of `SearchForm`.
Apr 24, 2025
b1dd57c
Conform `ListableElement` to `MarkupElement`.
Apr 24, 2025
ed257fc
Fix bug in search.js that stops result-item HTML from showing.
Apr 24, 2025
fa9c3e1
Fix button sizing in `Form`. Minor code cleanup.
Apr 24, 2025
9bf2b4a
Fix bug in `configuredAsNavigationItem()`. Add internal `style()` mod…
Apr 24, 2025
11da39d
Polish `NavigationBar` layout.
Apr 24, 2025
df08029
Update `badgeRoles` to `standardRoles` since used with other types.
Apr 24, 2025
14a824a
Misc. bug fixes.
Apr 24, 2025
5e188cc
Fix tests.
Apr 25, 2025
5aa83d1
Fix crash caused by wrong `lastModified` date format.
Apr 25, 2025
27bb18c
Fix warning.
Apr 25, 2025
8eb55c1
Add test for typed content.
Apr 25, 2025
133931a
Perform rendering in reversed order to accomodate context updates
TomaszLizer Apr 16, 2025
0a670cf
Merge pull request #806 from TomaszLizer/fix/initial-pass-highlight-i…
JPToroDev Apr 25, 2025
c88fe21
Add QR code to run command to easily view site on mobile device.
Apr 28, 2025
90c07bf
Merge remote-tracking branch 'refs/remotes/upstream/v0.6-beta'
Apr 28, 2025
9db1aa3
Fix escaping issue in font names.
Apr 28, 2025
cd2f0c4
Move file to eliminate build warning in terminal.
Apr 28, 2025
6eef046
Fix SwiftLint warnings.
Apr 28, 2025
97c65d9
Rename folder.
Apr 28, 2025
1312e07
Fix header.
Apr 28, 2025
99a5206
Fix ambiguous use error for `width()`.
Apr 28, 2025
d00adf8
Add `defaultLinkTarget()` modifier to `Head` to set default target fo…
Apr 28, 2025
dd923ae
Have `SearchForm` use search-specific keyboard on mobile. Add `width(…
Apr 28, 2025
ecc4468
Add init to `Text` that takes a custom parser.
Apr 28, 2025
c2914f3
Fix incorrect server file location
MrSkwiggs Apr 29, 2025
03f5ce0
Merge pull request #813 from twostraws/fix-make-install
MrSkwiggs Apr 29, 2025
ee1281b
Add modifiers to `Accordion` and `Item` to adjust styling.
Apr 29, 2025
745bfc9
Remove unneeded `Stylable` protocol.
Apr 29, 2025
84861d2
Merge remote-tracking branch 'refs/remotes/upstream/v0.6-beta'
Apr 29, 2025
79bfbf6
Rename `Accordion.Style.flush` to `.plain`. Make `ListStyle` `List.St…
May 1, 2025
5b37b6b
Add convenience static properties to `ListMarkerStyle`. Minor code cl…
May 1, 2025
ceacd37
Improve parameter names in `Accordion`.
May 1, 2025
f14e8eb
Clean up documentation.
May 1, 2025
e8b787b
Add `init(httpEquivalent: String, content: String)` to `MetaTag`. Fix…
May 1, 2025
3821033
Update `List.Style` cases to better mirror SwiftUI.
May 1, 2025
aef4630
Fix bug hiding numbers of ordered list items.
May 1, 2025
7d0e5fe
Fix `init(markdown: String)` in `Text`.
May 1, 2025
d8025ea
Fix `logo` layout.
May 1, 2025
fd59a30
Clean up `Section` init.
May 1, 2025
26ea579
Update `NavigationBar` API to use modifiers instead of a closure for …
May 2, 2025
07dd7fa
Add `NavigationItemGroup` type.
May 2, 2025
7904991
Delete empty file.
May 2, 2025
7553e9b
Remove site-search functionality.
May 2, 2025
ff2bf3c
Remove trailing comma.
May 2, 2025
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ install:
@echo "Installing the Ignite command-line tool...\\n"
@mkdir -p $(PREFIX_DIR) 2> /dev/null || ( echo "❌ Unable to create install directory \`$(PREFIX_DIR)\`. You might need to run \`sudo make\`\\n"; exit 126 )
@(install .build/release/IgniteCLI $(PREFIX_DIR)/ignite && \
install Sources/IgniteCLI/server.py $(PREFIX_DIR)/ignite-server.py && \
install ./server.py $(PREFIX_DIR)/ignite-server.py && \
chmod +x $(PREFIX_DIR)/ignite && \
(echo \\n✅ Success! Run \`ignite\` to get started.)) || \
(echo \\n❌ Installation failed. You might need to run \`sudo make\` instead.\\n)
Expand Down
34 changes: 24 additions & 10 deletions Sources/Ignite/Actions/Event Modifiers/EventModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,28 @@
// See LICENSE for license information.
//

private extension HTML {
func eventModifier(type: EventType, actions: [Action]) -> any HTML {
guard !actions.isEmpty else { return self }
// Custom elements need to be wrapped in a primitive container to store attributes
var copy: any HTML = self.isPrimitive ? self : Section(self)
copy.attributes.events.append(Event(name: type.rawValue, actions: actions))
return copy
}
@MainActor
private func eventModifier(
_ type: EventType,
actions: [Action],
content: any HTML
) -> any HTML {
guard !actions.isEmpty else { return content }
var copy: any HTML = content.isPrimitive ? content : Section(content)
copy.attributes.events.append(Event(name: type.rawValue, actions: actions))
return copy
}

@MainActor
private func eventModifier(
_ type: EventType,
actions: [Action],
content: any InlineElement
) -> any InlineElement {
guard !actions.isEmpty else { return content }
var copy: any InlineElement = content.isPrimitive ? content : Span(content)
copy.attributes.events.append(Event(name: type.rawValue, actions: actions))
return copy
}

public extension HTML {
Expand All @@ -22,7 +36,7 @@ public extension HTML {
/// - actions: Array of actions to execute when the event occurs
/// - Returns: A modified HTML element with the specified attribute.
func onEvent(_ type: EventType, _ actions: [Action]) -> some HTML {
AnyHTML(eventModifier(type: type, actions: actions))
AnyHTML(eventModifier(type, actions: actions, content: self))
}
}

Expand All @@ -33,6 +47,6 @@ public extension InlineElement {
/// - actions: Array of actions to execute when the event occurs
/// - Returns: A modified HTML element with the specified attribute.
func onEvent(_ type: EventType, _ actions: [Action]) -> some InlineElement {
AnyHTML(eventModifier(type: type, actions: actions))
AnyInlineElement(eventModifier(type, actions: actions, content: self))
}
}
22 changes: 14 additions & 8 deletions Sources/Ignite/Actions/Event Modifiers/HoverModifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,26 @@
// See LICENSE for license information.
//

private extension HTML {
func hoverModifier(hover: [Action], unhover: [Action]) -> any HTML {
self
.onEvent(.mouseOver, hover)
.onEvent(.mouseOut, unhover)
}
@MainActor
private func hoverModifier(hover: [Action], unhover: [Action], content: any HTML) -> any HTML {
content
.onEvent(.mouseOver, hover)
.onEvent(.mouseOut, unhover)
}

@MainActor
private func hoverModifier(hover: [Action], unhover: [Action], content: any InlineElement) -> any InlineElement {
content
.onEvent(.mouseOver, hover)
.onEvent(.mouseOut, unhover)
}

public extension HTML {
/// Adds "onmouseover" and "onmouseout" JavaScript events to this element.
/// - Parameter actions: A closure that takes a Boolean indicating hover state and returns actions to execute.
/// - Returns: A modified HTML element with the hover event handlers attached.
func onHover(@ActionBuilder actions: (_ isHovering: Bool) -> [Action]) -> some HTML {
AnyHTML(hoverModifier(hover: actions(true), unhover: actions(false)))
AnyHTML(hoverModifier(hover: actions(true), unhover: actions(false), content: self))
}
}

Expand All @@ -27,6 +33,6 @@ public extension InlineElement {
/// - Parameter actions: A closure that takes a Boolean indicating hover state and returns actions to execute.
/// - Returns: A modified inline HTML element with the hover event handlers attached.
func onHover(@ActionBuilder actions: (_ isHovering: Bool) -> [Action]) -> some InlineElement {
AnyHTML(hoverModifier(hover: actions(true), unhover: actions(false)))
AnyInlineElement(hoverModifier(hover: actions(true), unhover: actions(false), content: self))
}
}
116 changes: 0 additions & 116 deletions Sources/Ignite/Actions/SubscribeAction.swift

This file was deleted.

2 changes: 1 addition & 1 deletion Sources/Ignite/Components/FeedLink.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public struct FeedLink: HTML {
}

Link("RSS Feed", target: feedConfig.path)
EmptyHTML()
EmptyInlineElement()
}
.horizontalAlignment(.center)
}
Expand Down
7 changes: 4 additions & 3 deletions Sources/Ignite/Elements/Abbreviation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/// Renders an abbreviation.
public struct Abbreviation: InlineElement {
/// The content and behavior of this HTML.
public var body: some HTML { self }
public var body: some InlineElement { self }

/// The standard set of control attributes for HTML elements.
public var attributes = CoreAttributes()
Expand Down Expand Up @@ -41,7 +41,8 @@ public struct Abbreviation: InlineElement {

/// Renders this element using publishing context passed in.
/// - Returns: The HTML for this element.
public func render() -> String {
"<abbr\(attributes)>\(contents.render())</abbr>"
public func markup() -> Markup {
let contentHTML = contents.markupString()
return Markup("<abbr\(attributes)>\(contentHTML)</abbr>")
}
}
78 changes: 75 additions & 3 deletions Sources/Ignite/Elements/Accordion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@ public struct Accordion: HTML {
case all
}

/// The visual style of the accordion.
public enum Style: Sendable {
/// A style with outer borders and rounded corners.
case bordered

/// Removes outer borders and rounded corners.
case plain

/// The default styling based on context.
public static var automatic: Self { .bordered }
}

/// The content and behavior of this HTML.
public var body: some HTML { self }

Expand All @@ -27,7 +39,7 @@ public struct Accordion: HTML {
public var isPrimitive: Bool { true }

/// A collection of sections you want to show inside this accordion.
var items: [Item]
private var items: [Item]

/// Adjusts what happens when a section is opened.
/// Defaults to `.individual`, meaning that only one
Expand Down Expand Up @@ -60,9 +72,69 @@ public struct Accordion: HTML {
return copy
}

/// Sets the visual style of the accordion.
/// - Parameter style: The style to apply to the accordion.
/// - Returns: A modified copy of this accordion with the new style applied.
public func accordionStyle(_ style: Style) -> Self {
var copy = self
copy.attributes.append(classes: "accordion-flush")
return copy
}

/// Sets different background colors for normal and active states of accordion headers.
/// - Parameters:
/// - closed: The color to use for normal (inactive) headers.
/// - open: The color to use for active (selected) headers.
/// - Returns: A modified copy of this accordion with the new header backgrounds.
public func headerBackground(_ closed: Color, open: Color) -> Self {
var copy = self
copy.attributes.append(styles: .init("--bs-accordion-btn-bg", value: closed.description))
copy.attributes.append(styles: .init("--bs-btn-hover-bg", value: closed.description))
copy.attributes.append(styles: .init("--bs-btn-active-bg", value: closed.description))
copy.attributes.append(styles: .init("--bs-accordion-active-bg", value: open.description))
return copy
}

/// Sets the same background color for both normal and active states of accordion headers.
/// - Parameter color: The color to use for all header states.
/// - Returns: A modified copy of this accordion with the new header background.
public func headerBackground(_ color: Color) -> Self {
self.headerBackground(color, open: color)
}

/// Sets different text colors for normal and active states of accordion headers.
/// - Parameters:
/// - closed: The text color to use for normal (inactive) headers.
/// - open: The text color to use for active (selected) headers.
/// - Returns: A modified copy of this accordion with the new header text colors.
public func headerForegroundStyle(_ closed: Color, open: Color) -> Self {
var copy = self
copy.attributes.append(styles: .init("--bs-accordion-btn-color", value: closed.description))
copy.attributes.append(styles: .init("--bs-btn-hover-color", value: closed.description))
copy.attributes.append(styles: .init("--bs-btn-active-color", value: closed.description))
copy.attributes.append(styles: .init("--bs-accordion-active-color", value: open.description))
return copy
}

/// Sets the same text color for both normal and active states of accordion headers.
/// - Parameter color: The text color to use for all header states.
/// - Returns: A modified copy of this accordion with the new header text color.
public func headerForegroundStyle(_ color: Color) -> Self {
self.headerForegroundStyle(color, open: color)
}

/// Sets the border color for the accordion.
/// - Parameter color: The color to use for accordion borders.
/// - Returns: A modified copy of this accordion with the new border color.
public func borderColor(_ color: Color) -> Self {
var copy = self
copy.attributes.append(styles: .init("--bs-accordion-border-color", value: color.description))
return copy
}

/// Renders this element using publishing context passed in.
/// - Returns: The HTML for this element.
public func render() -> String {
public func markup() -> Markup {
// Accordions with an individual open mode must have
// each element linked back to a unique accordion ID.
// This is generated below, then passed into individual
Expand All @@ -77,6 +149,6 @@ public struct Accordion: HTML {
.class("accordion")
.id(accordionID)

return content.render()
return content.markup()
}
}
4 changes: 2 additions & 2 deletions Sources/Ignite/Elements/Alert.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ public struct Alert: HTML {

/// Renders this element using publishing context passed in.
/// - Returns: The HTML for this element.
public func render() -> String {
public func markup() -> Markup {
Section(content)
.class(alertClasses)
.attributes(attributes)
.render()
.markup()
}
}
6 changes: 3 additions & 3 deletions Sources/Ignite/Elements/ArticlePreview.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,17 @@ public struct ArticlePreview: HTML {

/// Renders the article preview with either a custom layout or the default card.
/// - Returns: A rendered string of HTML.
public func render() -> String {
public func markup() -> Markup {
// If custom style is provided, use it; otherwise,
// fallback to default layout.
if let style {
style.body(content: article)
.attributes(attributes)
.render()
.markup()
} else {
defaultCardLayout()
.attributes(attributes)
.render()
.markup()
}
}

Expand Down
Loading