Last active
September 4, 2023 15:48
-
-
Save bsrz/54a5ea369d304334519e58527eb1a3bd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| .DS_Store | |
| /build | |
| /.build | |
| /.swiftpm | |
| /*.xcodeproj | |
| .publish | |
| # Ignore the output | |
| /Output |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| struct ItemMetadata: WebsiteItemMetadata { | |
| // Add any site-specific metadata that you want to use here. | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Foundation | |
| import Publish | |
| import Plot | |
| // This type acts as the configuration for your website. | |
| struct HelloPublish: Website { | |
| enum SectionID: String, WebsiteSectionID { | |
| // Add the sections that you want your website to contain here: | |
| case posts | |
| } | |
| struct ItemMetadata: WebsiteItemMetadata { | |
| // Add any site-specific metadata that you want to use here. | |
| } | |
| // Update these properties to configure your website: | |
| var url = URL(string: "https://your-website-url.com")! | |
| var name = "HelloPublish" | |
| var description = "A description of HelloPublish" | |
| var language: Language { .english } | |
| var imagePath: Path? { nil } | |
| } | |
| // This will generate your website using the built-in Foundation theme: | |
| try HelloPublish().publish(withTheme: .foundation) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // This will generate your website using the built-in Foundation theme: | |
| try HelloPublish().publish(withTheme: .foundation) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| try HelloPublish().publish(withTheme: .hello) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| enum SectionID: String, WebsiteSectionID { | |
| // Add the sections that you want your website to contain here: | |
| case posts | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| HelloPublish (root) | |
| ├── Content | |
| │ ├── index.md | |
| │ └── posts | |
| │ ├── first-post.md | |
| │ └── index.md | |
| ├── Mintfile | |
| ├── Output | |
| │ ├── feed.rss | |
| │ ├── index.html | |
| │ ├── posts | |
| │ │ ├── first-post | |
| │ │ │ └── index.html | |
| │ │ └── index.html | |
| │ ├── sitemap.xml | |
| │ ├── styles.css | |
| │ └── tags | |
| │ ├── article | |
| │ │ └── index.html | |
| │ ├── first | |
| │ │ └── index.html | |
| │ └── index.html | |
| ├── Package.resolved | |
| ├── Package.swift | |
| ├── Resources | |
| └── Sources | |
| └── HelloPublish | |
| └── main.swift |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Resources | |
| ├── images | |
| └── styles |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Resources | |
| ├── images | |
| │ └── posts | |
| │ ├── 0001 | |
| │ │ ├── hero.png | |
| │ │ └── thumbnail.png | |
| │ ├── 0002 | |
| │ │ ├── hero.png | |
| │ │ └── thumbnail.png | |
| │ ├── Nth | |
| │ │ ├── hero.png | |
| │ │ └── thumbnail.png | |
| │ ↓ | |
| └── styles | |
| └── main.css |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Publish | |
| * Copyright (c) John Sundell 2019 | |
| * MIT license, see LICENSE file for details | |
| */ | |
| import Plot | |
| public extension Theme { | |
| /// The default "Foundation" theme that Publish ships with, a very | |
| /// basic theme mostly implemented for demonstration purposes. | |
| static var foundation: Self { | |
| Theme( | |
| htmlFactory: FoundationHTMLFactory(), | |
| resourcePaths: ["Resources/FoundationTheme/styles.css"] | |
| ) | |
| } | |
| } | |
| private struct FoundationHTMLFactory<Site: Website>: HTMLFactory { | |
| func makeIndexHTML(for index: Index, | |
| context: PublishingContext<Site>) throws -> HTML | |
| { | |
| HTML( | |
| .lang(context.site.language), | |
| .head(for: index, on: context.site), | |
| .body { | |
| SiteHeader(context: context, selectedSelectionID: nil) | |
| Wrapper { | |
| H1(index.title) | |
| Paragraph(context.site.description) | |
| .class("description") | |
| H2("Latest content") | |
| ItemList( | |
| items: context.allItems( | |
| sortedBy: \.date, | |
| order: .descending | |
| ), | |
| site: context.site | |
| ) | |
| } | |
| SiteFooter() | |
| } | |
| ) | |
| } | |
| func makeSectionHTML(for section: Section<Site>, | |
| context: PublishingContext<Site>) throws -> HTML | |
| { | |
| HTML( | |
| .lang(context.site.language), | |
| .head(for: section, on: context.site), | |
| .body { | |
| SiteHeader(context: context, selectedSelectionID: section.id) | |
| Wrapper { | |
| H1(section.title) | |
| ItemList(items: section.items, site: context.site) | |
| } | |
| SiteFooter() | |
| } | |
| ) | |
| } | |
| func makeItemHTML(for item: Item<Site>, | |
| context: PublishingContext<Site>) throws -> HTML | |
| { | |
| HTML( | |
| .lang(context.site.language), | |
| .head(for: item, on: context.site), | |
| .body( | |
| .class("item-page"), | |
| .components { | |
| SiteHeader(context: context, selectedSelectionID: item.sectionID) | |
| Wrapper { | |
| Article { | |
| Div(item.content.body).class("content") | |
| Span("Tagged with: ") | |
| ItemTagList(item: item, site: context.site) | |
| } | |
| } | |
| SiteFooter() | |
| } | |
| ) | |
| ) | |
| } | |
| func makePageHTML(for page: Page, | |
| context: PublishingContext<Site>) throws -> HTML | |
| { | |
| HTML( | |
| .lang(context.site.language), | |
| .head(for: page, on: context.site), | |
| .body { | |
| SiteHeader(context: context, selectedSelectionID: nil) | |
| Wrapper(page.body) | |
| SiteFooter() | |
| } | |
| ) | |
| } | |
| func makeTagListHTML(for page: TagListPage, | |
| context: PublishingContext<Site>) throws -> HTML? | |
| { | |
| HTML( | |
| .lang(context.site.language), | |
| .head(for: page, on: context.site), | |
| .body { | |
| SiteHeader(context: context, selectedSelectionID: nil) | |
| Wrapper { | |
| H1("Browse all tags") | |
| List(page.tags.sorted()) { tag in | |
| ListItem { | |
| Link(tag.string, | |
| url: context.site.path(for: tag).absoluteString) | |
| } | |
| .class("tag") | |
| } | |
| .class("all-tags") | |
| } | |
| SiteFooter() | |
| } | |
| ) | |
| } | |
| func makeTagDetailsHTML(for page: TagDetailsPage, | |
| context: PublishingContext<Site>) throws -> HTML? | |
| { | |
| HTML( | |
| .lang(context.site.language), | |
| .head(for: page, on: context.site), | |
| .body { | |
| SiteHeader(context: context, selectedSelectionID: nil) | |
| Wrapper { | |
| H1 { | |
| Text("Tagged with ") | |
| Span(page.tag.string).class("tag") | |
| } | |
| Link("Browse all tags", | |
| url: context.site.tagListPath.absoluteString) | |
| .class("browse-all") | |
| ItemList( | |
| items: context.items( | |
| taggedWith: page.tag, | |
| sortedBy: \.date, | |
| order: .descending | |
| ), | |
| site: context.site | |
| ) | |
| } | |
| SiteFooter() | |
| } | |
| ) | |
| } | |
| } | |
| private struct Wrapper: ComponentContainer { | |
| @ComponentBuilder var content: ContentProvider | |
| var body: Component { | |
| Div(content: content).class("wrapper") | |
| } | |
| } | |
| private struct SiteHeader<Site: Website>: Component { | |
| var context: PublishingContext<Site> | |
| var selectedSelectionID: Site.SectionID? | |
| var body: Component { | |
| Header { | |
| Wrapper { | |
| Link(context.site.name, url: "/") | |
| .class("site-name") | |
| if Site.SectionID.allCases.count > 1 { | |
| navigation | |
| } | |
| } | |
| } | |
| } | |
| private var navigation: Component { | |
| Navigation { | |
| List(Site.SectionID.allCases) { sectionID in | |
| let section = context.sections[sectionID] | |
| return Link(section.title, | |
| url: section.path.absoluteString) | |
| .class(sectionID == selectedSelectionID ? "selected" : "") | |
| } | |
| } | |
| } | |
| } | |
| private struct ItemList<Site: Website>: Component { | |
| var items: [Item<Site>] | |
| var site: Site | |
| var body: Component { | |
| List(items) { item in | |
| Article { | |
| H1(Link(item.title, url: item.path.absoluteString)) | |
| ItemTagList(item: item, site: site) | |
| Paragraph(item.description) | |
| } | |
| } | |
| .class("item-list") | |
| } | |
| } | |
| private struct ItemTagList<Site: Website>: Component { | |
| var item: Item<Site> | |
| var site: Site | |
| var body: Component { | |
| List(item.tags) { tag in | |
| Link(tag.string, url: site.path(for: tag).absoluteString) | |
| } | |
| .class("tag-list") | |
| } | |
| } | |
| private struct SiteFooter: Component { | |
| var body: Component { | |
| Footer { | |
| Paragraph { | |
| Text("Generated using ") | |
| Link("Publish", url: "https://github.com/johnsundell/publish") | |
| } | |
| Paragraph { | |
| Link("RSS feed", url: "/feed.rss") | |
| } | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public extension Theme { | |
| /// The default "Foundation" theme that Publish ships with, a very | |
| /// basic theme mostly implemented for demonstration purposes. | |
| static var foundation: Self { | |
| Theme( | |
| htmlFactory: FoundationHTMLFactory(), | |
| resourcePaths: ["Resources/FoundationTheme/styles.css"] | |
| ) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Publish | |
| public extension Theme { | |
| static var hello: Self { | |
| Theme( | |
| htmlFactory: HelloHTMLFactory(), | |
| resourcePaths: ["Resources/ThemeHello/styles.css"] | |
| ) | |
| } | |
| } | |
| private struct HelloHTMLFactory<Site: Website>: HTMLFactory { | |
| [...] | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func makeIndexHTML(for index: Index, context: PublishingContext<Site>) throws -> HTML | |
| func makeSectionHTML(for section: Section<Site>, context: PublishingContext<Site>) throws -> HTML | |
| func makeItemHTML(for item: Item<Site>, context: PublishingContext<Site>) throws -> HTML | |
| func makePageHTML(for page: Page, context: PublishingContext<Site>) throws -> HTML | |
| func makeTagListHTML(for page: TagListPage, context: PublishingContext<Site>) throws -> HTML? | |
| func makeTagDetailsHTML(for page: TagDetailsPage, context: PublishingContext<Site>) throws -> HTML? |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func makeIndexHTML(for index: Index, context: PublishingContext<Site>) throws -> HTML { | |
| HTML( | |
| .lang(context.site.language), | |
| .head(for: index, on: context.site), | |
| .body { | |
| SiteHeader(context: context, selectedSelectionID: nil) | |
| Wrapper { | |
| H1(index.title) | |
| Paragraph(context.site.description) | |
| .class("description") | |
| H2("Latest content") | |
| ItemList( | |
| items: context.allItems( | |
| sortedBy: \.date, | |
| order: .descending | |
| ), | |
| site: context.site | |
| ) | |
| } | |
| SiteFooter() | |
| } | |
| ) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func makeSectionHTML(for section: Section<Site>, context: PublishingContext<Site>) throws -> HTML { | |
| HTML( | |
| .lang(context.site.language), | |
| .head(for: section, on: context.site), | |
| .body { | |
| SiteHeader(context: context, selectedSelectionID: section.id) | |
| Wrapper { | |
| H1(section.title) | |
| ItemList(items: section.items, site: context.site) | |
| } | |
| SiteFooter() | |
| } | |
| ) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func makeItemHTML(for item: Item<Site>, context: PublishingContext<Site>) throws -> HTML { | |
| HTML( | |
| .lang(context.site.language), | |
| .head(for: item, on: context.site), | |
| .body( | |
| .class("item-page"), | |
| .components { | |
| SiteHeader(context: context, selectedSelectionID: item.sectionID) | |
| Wrapper { | |
| Article { | |
| Div(item.content.body).class("content") | |
| Span("Tagged with: ") | |
| ItemTagList(item: item, site: context.site) | |
| } | |
| } | |
| SiteFooter() | |
| } | |
| ) | |
| ) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func makePageHTML(for page: Page, context: PublishingContext<Site>) throws -> HTML { | |
| HTML( | |
| .lang(context.site.language), | |
| .head(for: page, on: context.site), | |
| .body { | |
| SiteHeader(context: context, selectedSelectionID: nil) | |
| Wrapper(page.body) | |
| SiteFooter() | |
| } | |
| ) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func makeTagListHTML(for page: TagListPage, context: PublishingContext<Site>) throws -> HTML? { | |
| HTML( | |
| .lang(context.site.language), | |
| .head(for: page, on: context.site), | |
| .body { | |
| SiteHeader(context: context, selectedSelectionID: nil) | |
| Wrapper { | |
| H1("Browse all tags") | |
| List(page.tags.sorted()) { tag in | |
| ListItem { | |
| Link(tag.string, | |
| url: context.site.path(for: tag).absoluteString) | |
| } | |
| .class("tag") | |
| } | |
| .class("all-tags") | |
| } | |
| SiteFooter() | |
| } | |
| ) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| func makeTagDetailsHTML(for page: TagDetailsPage, context: PublishingContext<Site>) throws -> HTML? { | |
| HTML( | |
| .lang(context.site.language), | |
| .head(for: page, on: context.site), | |
| .body { | |
| SiteHeader(context: context, selectedSelectionID: nil) | |
| Wrapper { | |
| H1 { | |
| Text("Tagged with ") | |
| Span(page.tag.string).class("tag") | |
| } | |
| Link("Browse all tags", | |
| url: context.site.tagListPath.absoluteString) | |
| .class("browse-all") | |
| ItemList( | |
| items: context.items( | |
| taggedWith: page.tag, | |
| sortedBy: \.date, | |
| order: .descending | |
| ), | |
| site: context.site | |
| ) | |
| } | |
| SiteFooter() | |
| } | |
| ) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment