Skip to content

Instantly share code, notes, and snippets.

@helje5
Last active July 16, 2022 22:24
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save helje5/7873853175af1490c85ed7253f4bb390 to your computer and use it in GitHub Desktop.
Small Swift Script to serve `.doccarchive`s to the browser
#!/usr/bin/swift sh
import MacroExpress // @Macro-swift
// MARK: - Parse Commandline Arguments & Usage
func usage() {
let tool = path.basename(process.argv.first ?? "servedocc")
print(
"""
Usage: \(tool) <docc archive folder>
Example:
\(tool) SlothCreator.doccarchive
"""
)
}
guard process.argv.count == 2 else {
usage()
process.exit(1)
}
let archivePath = process.argv[1]
let indexPath = archivePath + "/index.html"
let docPath = archivePath + "/data/documentation"
guard fs.existsSync(archivePath) else {
console.error("Specified file does not exist:", archivePath)
process.exit(2)
}
guard fs.existsSync(indexPath), fs.existsSync(docPath) else {
console.error("File does not look like a DocC archive:", archivePath)
process.exit(3)
}
guard let dataIndex = (try? fs.readdirSync(docPath))?
.first(where: { $0.hasSuffix(".json")} )
else {
console.error("File does not look like a DocC archive, missing data index:",
archivePath)
process.exit(3)
}
let dataIndexPath = docPath + "/" + dataIndex
// MARK: - Serve Individual Files
func serveFile(_ path: String) -> Middleware {
return { req, res, next in
fs.createReadStream(path)
.pipe(res)
.onError { error in
console.error("Failed to serve \(path):", error)
res.status(500)
}
}
}
// MARK: - Configure and Start the Server
let staticDirs = [ "css", "data", "downloads", "images", "img",
"index", "js", "videos" ]
let staticFiles = [ "favicon.ico", "favicon.svg", "theme-settings.json" ]
let app = express()
app.use(logger("dev"))
// Map all matching requests to this index.html
app.get("/documentation/*", serveFile(indexPath))
.get("/tutorials/*", serveFile(indexPath))
.get("/data/documentation.json", serveFile(dataIndexPath))
for path in staticDirs { // serve the whole directory ("/*" match)
app.get("/" + path + "/*", serveStatic(archivePath))
}
for path in staticFiles { // just serve the specific file
app.get("/" + path, serveStatic(archivePath))
}
// redirects
app.get("/tutorials") { _, res, _ in res.redirect("/tutorials/") }
.get("/documentation") { _, res, _ in res.redirect("/documentation/") }
.get { _, res, _ in res.redirect("/documentation/") }
app.listen(1337) {
console.log("Server listening on: http://localhost:1337/")
console.log("DocC Archive:", archivePath)
}
@helje5
Copy link
Author

helje5 commented Jun 26, 2021

This is a tiny Macro.swift server to serve "DocC" archives, a format to document Swift frameworks and packages: Documenting a Swift Framework or Package.

It is using the excellent swift-sh to grab the required packages (brew install mxcl/made/swift-sh). If a proper Swift package is desired, servedocc also comes as part of the MacroExpress Examples.

Example invocation:

$ ./servedocc.swift ~/Downloads/SlothCreator.doccarchive
2021-06-26T17:39:05+0200 notice μ.console : Server listening on: http://localhost:1337/
2021-06-26T17:39:05+0200 notice μ.console : DocC Archive: /Users/helge/Downloads/SlothCreator.doccarchive

Then access the documentation by visiting http://localhost:1337/ in your browser.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment