Skip to content

Commit

Permalink
WIP: implement
Browse files Browse the repository at this point in the history
  • Loading branch information
yorickpeterse committed May 31, 2024
1 parent 86834ba commit c568707
Show file tree
Hide file tree
Showing 3 changed files with 292 additions and 44 deletions.
2 changes: 1 addition & 1 deletion inko.pkg
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
require https://github.com/yorickpeterse/inko-wobsite 0.14.0 aefbbaf6d24cb4a6574c92573c0a72d14b863760
require https://github.com/yorickpeterse/inko-wobsite 0.16.0 8595e430857cb2579cfb2fe0ff19cc7446b516e4
require https://github.com/yorickpeterse/inko-builder 0.12.0 dfb7877ca9dec2109b0fa940190c210dd3fe4059
require https://github.com/yorickpeterse/inko-markdown 0.16.0 e6d26dd94bd44cdd24fb8a159caa949cfe82891f
131 changes: 102 additions & 29 deletions src/idoc/cmd/html.inko
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import idoc.ir (Constant, Module)
import std.fs.file (ReadOnlyFile, WriteOnlyFile)
import builder.html (Document)
import idoc.ir (Module)
import std.fs.file (WriteOnlyFile)
import std.fs.path (Path)
import std.io (Write)
import std.json (Error, PullParser)
import std.json (Error)
import std.optparse (Help, Options)
import std.range (InclusiveRange)
import std.time (DateTime)
import wobsite (Files, FrontMatter, Page, Site, UpdateAssetLinks)
import wobsite.url (file_url)

# The default directory in which to look for the output of `inko doc`.
#
Expand All @@ -27,6 +30,58 @@ fn usage(options: ref Options, output: mut Write) {
let _ = output.write_string(help)
}

class async Parser {
fn async parse(
input: uni Path,
output: Channel[uni Result[Module, (Path, Error)]],
) {
let res = recover {
let input = recover input

match Module.parse_file(input.clone) {
case Ok(mod) -> Result.Ok(mod)
case Error(e) -> Result.Error((input, e))
}
}

output.send(res)
}
}

fn generate(source: String, files: ref Files, module: ref Module) -> String {
# TODO: do the actual work
# TODO: update heading levels:
# TODO: push into function/type/whatever
let url = file_url(files.source, source.to_path)
# let page = Page(
# front_matter: FrontMatter(title: 'TITLE', date: DateTime.new),
# url: url,
# source_path: 'TODO'.to_path,
# body: panic('TODO'),
# )

let page = Document.html('en', fn (html) {
html.head.with(fn (h) {
# TODO
})

html.body.with(fn (b) {
# TODO
})
})

# let body = match mod.documentation {
# case Some(d) -> {
# let html = d.to_html
#
# UpdateAssetLinks.new(files, url).run(html)
# html.to_string
# }
# case _ -> ''
# }
page.to_string
}

fn run(
arguments: Array[String],
working_directory: ref Path,
Expand All @@ -49,48 +104,66 @@ fn run(

# TODO:
#
# - Parse the JSON files
# - Convert the JSON data to Markdown files, one for each module. Write these
# build/idoc/source/
# - Adjust the headings in examples to be of the right level
# - Wrap documentation headings such that we don't include them in the table
# of contents.
# - Do all this in parallel
# - Copy assets (e.g. CSS) from /usr/share/whatever to build/idoc/source/
# - Generate static website using inko-wobsite, write to build/idoc/public/

let files = try input
let build = OUTPUT_DIR.to_path
let source = build.join('source')

# Make sure we always start with a clean directory, instead of keeping files
# from previous builds around.
let _ = build.remove_directory_all

try source.create_directory_all.map_error(fn (e) {
'failed to create ${source}: ${e}'
})

let site = try Site.new(source, build.join('public')).map_error(fn (e) {
'failed to set up the site generator: ${e}'
})

let modules = Channel.new(size: 32)
let mut pending = try input
.list
.then(fn (iter) {
iter.try_reduce([], fn (acc, res) {
iter.try_reduce(0, fn (sum, res) {
match res {
case Ok({ @path = path, @type = File }) -> {
match path.extension {
case Some('json') -> acc.push(path)
case _ -> {}
}
case Ok({ @path = p, @type = File }) if p.extension.or('') == 'json'
-> {
Parser().parse(recover p.clone, modules)
Result.Ok(sum + 1)
}
case Error(e) -> throw e
case _ -> {}
case Ok(_) -> Result.Ok(sum)
case Error(e) -> Result.Error(e)
}

Result.Ok(acc)
})
})
.map_error(fn (e) { 'failed to get the JSON input files: ${e}' })
.map_error(fn (e) { 'failed to get the JSON files to process: ${e}' })

let dir = OUTPUT_DIR.to_path
let md_dir = dir.join('source/modules')
while pending > 0 {
let mod = recover {
match modules.receive {
case Ok(v) -> v
case Error((p, e)) -> throw 'failed to parse the JSON file ${p}: ${e}'
}
}

try md_dir.create_directory_all.map_error(fn (e) {
"failed to create '${md_dir}': ${e}"
})
let dir = 'module/' + mod.name.replace('.', '/')

try files.into_iter.try_each(fn (path) {
try Module.parse_file(path.clone).map_error(fn (e) {
'failed to parse ${path}: ${e}'
site.generate(dir + '/index.html', fn move (files) {
Result.Ok(generate(dir + '/index.md', files, mod))
})

Result.Ok(nil)
})
pending -= 1
}

Result.Ok(nil)
match site.wait {
case Ok(_) -> Result.Ok(nil)
case Error(e) -> Result.Error('failed to build the documentation: ${e}')
}
}
Loading

0 comments on commit c568707

Please sign in to comment.