mirror of
https://github.com/samsonjs/samhuri.net.git
synced 2026-03-25 09:05:47 +00:00
Make the site generator recursively render public files
- Now renders markdown - Separates templates from content now
This commit is contained in:
parent
b11e0686ad
commit
2ce8d2f376
8 changed files with 80 additions and 24 deletions
|
|
@ -1,6 +1,15 @@
|
|||
{
|
||||
"object": {
|
||||
"pins": [
|
||||
{
|
||||
"package": "Ink",
|
||||
"repositoryURL": "https://github.com/johnsundell/ink.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "af743ad6882bfe1adb0acf7453d36d2075ebb1d5",
|
||||
"version": "0.1.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "PathKit",
|
||||
"repositoryURL": "https://github.com/kylef/PathKit.git",
|
||||
|
|
|
|||
|
|
@ -6,16 +6,14 @@ import PackageDescription
|
|||
let package = Package(
|
||||
name: "SiteGenerator",
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/stencilproject/Stencil.git", from: "0.13.0")
|
||||
.package(url: "https://github.com/stencilproject/Stencil.git", from: "0.13.0"),
|
||||
.package(url: "https://github.com/johnsundell/ink.git", from: "0.1.0"),
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
|
||||
.target(
|
||||
name: "SiteGenerator",
|
||||
dependencies: ["Stencil"]),
|
||||
.testTarget(
|
||||
name: "SiteGeneratorTests",
|
||||
dependencies: ["SiteGenerator"]),
|
||||
.target( name: "SiteGenerator", dependencies: [
|
||||
"Ink",
|
||||
"Stencil",
|
||||
]),
|
||||
.testTarget(name: "SiteGeneratorTests", dependencies: ["SiteGenerator"]),
|
||||
]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import Ink
|
||||
import PathKit
|
||||
import Stencil
|
||||
|
||||
|
|
@ -16,19 +17,72 @@ public final class Generator {
|
|||
public let sourceURL: URL
|
||||
|
||||
private let renderer: Environment
|
||||
private let mdParser: MarkdownParser
|
||||
|
||||
public init(sourceURL: URL) throws {
|
||||
let publicURL = sourceURL.appendingPathComponent("public")
|
||||
self.renderer = Environment(loader: FileSystemLoader(paths: [Path(publicURL.path)]))
|
||||
let siteURL = sourceURL.appendingPathComponent("site.json")
|
||||
self.site = try Site.decode(from: siteURL)
|
||||
self.sourceURL = sourceURL
|
||||
|
||||
let templatesURL = sourceURL.appendingPathComponent("templates")
|
||||
self.renderer = Environment(loader: FileSystemLoader(paths: [Path(templatesURL.path)]))
|
||||
|
||||
self.mdParser = MarkdownParser(modifiers: [])
|
||||
}
|
||||
|
||||
public func generate(targetURL: URL) throws {
|
||||
try fileManager.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil)
|
||||
let indexHTML = try renderer.renderTemplate(name: "index.html", context: ["site": site])
|
||||
let indexURL = targetURL.appendingPathComponent("index.html")
|
||||
try indexHTML.write(to: indexURL, atomically: true, encoding: .utf8)
|
||||
// Iterate through all files in public recursively and render or copy each one
|
||||
let publicURL = sourceURL.appendingPathComponent("public")
|
||||
try renderPath(publicURL.path, to: targetURL)
|
||||
}
|
||||
|
||||
func renderPath(_ path: String, to targetURL: URL) throws {
|
||||
for filename in try fileManager.contentsOfDirectory(atPath: path) {
|
||||
|
||||
// Recurse into subdirectories, updating the target directory as well.
|
||||
let fileURL = URL(fileURLWithPath: path).appendingPathComponent(filename)
|
||||
var isDir: ObjCBool = false
|
||||
fileManager.fileExists(atPath: fileURL.path, isDirectory: &isDir)
|
||||
guard !isDir.boolValue else {
|
||||
try renderPath(fileURL.path, to: targetURL.appendingPathComponent(filename))
|
||||
return
|
||||
}
|
||||
|
||||
// Make sure this path exists so we can write to it.
|
||||
try fileManager.createDirectory(at: targetURL, withIntermediateDirectories: true, attributes: nil)
|
||||
|
||||
// Handle the file, transforming it if necessary.
|
||||
let ext = filename.split(separator: ".").last!
|
||||
switch ext {
|
||||
|
||||
case "md":
|
||||
let htmlURL = targetURL.appendingPathComponent(filename.replacingOccurrences(of: ".md", with: ".html"))
|
||||
try renderMarkdown(from: fileURL, to: htmlURL, template: "site", context: [:])
|
||||
|
||||
default:
|
||||
// Who knows. Copy the file unchanged.
|
||||
let src = URL(fileURLWithPath: path).appendingPathComponent(filename)
|
||||
let dest = targetURL.appendingPathComponent(filename)
|
||||
try fileManager.copyItem(at: src, to: dest)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func renderMarkdown(
|
||||
from sourceURL: URL,
|
||||
to targetURL: URL,
|
||||
template: String,
|
||||
context: [String: Any]
|
||||
) throws {
|
||||
let bodyMarkdown = try String(contentsOf: sourceURL, encoding: .utf8)
|
||||
let bodyResult = mdParser.parse(bodyMarkdown)
|
||||
let bodyHTML = bodyResult.html.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
var context = context
|
||||
context["site"] = site
|
||||
context["body"] = bodyHTML
|
||||
context.merge(bodyResult.metadata, uniquingKeysWith: { _, new in new })
|
||||
let siteHTML = try renderer.renderTemplate(name: "\(template).html", context: context)
|
||||
try siteHTML.write(to: targetURL, atomically: true, encoding: .utf8)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
bin/test
1
bin/test
|
|
@ -8,6 +8,7 @@ cp .build/x86_64-apple-macosx/debug/SiteGenerator ../bin/sitegen
|
|||
popd >/dev/null
|
||||
|
||||
for site in Tests/test-*; do
|
||||
rm -rf "$site/actual"
|
||||
bin/compile "$site/in" "$site/actual" # >/dev/null
|
||||
diff -ru "$site/expected" "$site/actual"
|
||||
rm -r "$site/actual"
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
</head>
|
||||
<body>
|
||||
<h1><a href="http://example.net">Valar Morghulis</a></h1>
|
||||
|
||||
<p>hello world</p>
|
||||
|
||||
<p>hello world</p>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,4 +0,0 @@
|
|||
{% extends "layout.html" %}
|
||||
{% block content %}
|
||||
<p>hello world</p>
|
||||
{% endblock %}
|
||||
1
tests/test-index/in/public/index.md
Normal file
1
tests/test-index/in/public/index.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
hello world
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
</head>
|
||||
<body>
|
||||
<h1><a href="{{ site.url }}">{{ site.title }}</a></h1>
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
{{ body }}
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in a new issue