From 116160972cf5773b20a89cdfec46c4d1dfd4c314 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Sat, 29 Jun 2024 21:08:30 +0800 Subject: [PATCH] Update manual generator for 0.15.0 --- docs/inko.pkg | 6 +- docs/src/docs/config.inko | 30 ++++---- docs/src/docs/filters.inko | 15 ++-- docs/src/docs/layouts.inko | 154 ++++++++++++++++++------------------- docs/src/docs/menu.inko | 64 ++++++++------- docs/src/docs/url.inko | 10 +-- docs/src/main.inko | 22 +++--- 7 files changed, 147 insertions(+), 154 deletions(-) diff --git a/docs/inko.pkg b/docs/inko.pkg index 1b4060bab..86ed2bfc4 100644 --- a/docs/inko.pkg +++ b/docs/inko.pkg @@ -1,3 +1,3 @@ -require https://github.com/yorickpeterse/inko-wobsite 0.13.0 086ccf8634e494f18fed2c72329567a39c726012 -require https://github.com/yorickpeterse/inko-builder 0.11.0 ae7b8cf3476dfc401408c493bd6d795bd0ac3ab2 -require https://github.com/yorickpeterse/inko-markdown 0.15.0 48cf0e8276522870a601f857f672c5a11c5eda37 +require https://github.com/yorickpeterse/inko-wobsite 0.17.0 1078263e2219842fcfeed309ef57acd803f0501a +require https://github.com/yorickpeterse/inko-builder 0.12.0 dfb7877ca9dec2109b0fa940190c210dd3fe4059 +require https://github.com/yorickpeterse/inko-markdown 0.20.0 f3e1021ac8eb00ddca6490d26c49b4c82524d23c diff --git a/docs/src/docs/config.inko b/docs/src/docs/config.inko index 8376cac2d..bcb6cee7e 100644 --- a/docs/src/docs/config.inko +++ b/docs/src/docs/config.inko @@ -1,7 +1,7 @@ -import docs.menu.Menu -import std.clone.Clone -import std.fs.path.Path -import wobsite.Page +import docs.menu (Menu) +import std.clone (Clone) +import std.fs.path (Path) +import wobsite (Page) let MENU_FILE = 'menu.json' @@ -18,24 +18,24 @@ class pub Config { fn pub static new(source: ref Path) -> Result[Config, String] { let menu = try Menu.parse(source, Path.new(MENU_FILE)) - Result.Ok({Config { - @title = 'The Inko manual', - @base_url = 'https://docs.inko-lang.org/manual', - @menu = menu, - }}) + Result.Ok( + { + Config( + title: 'The Inko manual', + base_url: 'https://docs.inko-lang.org/manual', + menu: menu, + ) + }, + ) } fn canonical_url(page: ref Page) -> String { - "{@base_url}/latest{page.url}" + '${@base_url}/latest${page.url}' } } impl Clone[Config] for Config { fn pub clone -> Config { - Config { - @title = @title, - @base_url = @base_url, - @menu = @menu.clone, - } + Config(title: @title, base_url: @base_url, menu: @menu.clone) } } diff --git a/docs/src/docs/filters.inko b/docs/src/docs/filters.inko index 8cba76782..6c71d4654 100644 --- a/docs/src/docs/filters.inko +++ b/docs/src/docs/filters.inko @@ -1,14 +1,14 @@ -import builder.html.(Document, Element) -import docs.menu.Menu -import docs.url.(link_from, relative?) -import markdown.html.(Filter, TableOfContents) -import wobsite.Page -import wobsite.url.(relative_to_absolute) +import builder.html (Document, Element) +import docs.menu (Menu) +import docs.url (link_from, relative?) +import markdown.html (Filter, TableOfContents) +import wobsite (Page) +import wobsite.url (relative_to_absolute) # A filter that automatically inserts a table of contents. class AutoTableOfContents { fn static new -> AutoTableOfContents { - AutoTableOfContents {} + AutoTableOfContents() } fn add_marker(document: mut Document) { @@ -56,6 +56,7 @@ class RelativeLinks { let mut abs = relative_to_absolute(@page.url, relative, as_file: false) if abs.ends_with?('/').false? { abs = abs + '/' } + @menu.titles.opt(abs) } } diff --git a/docs/src/docs/layouts.inko b/docs/src/docs/layouts.inko index 24d598cb7..9ec9d3cc6 100644 --- a/docs/src/docs/layouts.inko +++ b/docs/src/docs/layouts.inko @@ -1,21 +1,21 @@ import builder.html import builder.xml -import docs.config.Config -import docs.filters.(AutoTableOfContents, RelativeLinks) -import docs.menu.(Item, Menu) -import docs.url.(link_from) -import markdown.html.(Filter, TableOfContents) -import std.string.StringBuffer -import wobsite.(Files, Page) -import wobsite.markdown.(Admonitions, SyntaxHighlight) -import wobsite.time.(human_readable_date, iso_date) +import docs.config (Config) +import docs.filters (AutoTableOfContents, RelativeLinks) +import docs.menu (Item, Menu) +import docs.url (link_from) +import markdown.html (Filter, TableOfContents) +import std.string (StringBuffer) +import wobsite (Files, Page) +import wobsite.markdown (Admonitions, SyntaxHighlight) +import wobsite.time (human_readable_date, iso_date) fn filters(menu: ref Menu, page: ref Page) -> Array[Filter] { [ SyntaxHighlight.new as Filter, Admonitions.new as Filter, - RelativeLinks { @menu = menu, @page = page } as Filter, - AutoTableOfContents {} as Filter, # This filter must come last + RelativeLinks(menu: menu, page: page) as Filter, + AutoTableOfContents() as Filter, # This filter must come last ] } @@ -57,22 +57,26 @@ fn sidebar_list( page: ref Page, ) { root.header.h1.text(title) - root.ul.with fn (ul) { - items.iter.each fn (item) { + root.ul.with(fn (ul) { + items.iter.each(fn (item) { let a = ul.li.a if item.url == page.url { a.attr('class', 'current') } + a.attr('href', link_from(page, item.url)).text(item.title) - } - } + }) + }) } fn sidebar(config: ref Config, root: mut html.Element, page: ref Page) { - let section = config.menu.items.iter.find fn (pair) { - pair.value.iter.any? fn (item) { item.url == page.url } - } + let section = config.menu.items.iter.find(fn (pair) { + pair.value.iter.any?(fn (item) { item.url == page.url }) + }) - let pair = match section { case Some(v) -> v, case _ -> return } + let pair = match section { + case Some(v) -> v + case _ -> return + } let left = root.aside.attr('class', 'left') sidebar_list(left, pair.key, pair.value, page) @@ -81,9 +85,9 @@ fn sidebar(config: ref Config, root: mut html.Element, page: ref Page) { fn home_sidebar(config: ref Config, root: mut html.Element, page: ref Page) { let left = root.aside.attr('class', 'left') - config.menu.items.iter.each fn (pair) { + config.menu.items.iter.each(fn (pair) { sidebar_list(left, pair.key, pair.value, page) - } + }) } fn toggle_menu(query: String, open: String, close: String) -> html.Element { @@ -107,24 +111,16 @@ fn head(config: ref Config, page: ref Page) -> html.Element { .meta .attr( 'content', - "\ - default-src 'self'; \ - script-src 'self'; \ - object-src 'none'; \ - style-src 'self'; \ - font-src 'self' data:; \ - base-uri 'none'; \ - form-action 'none'; \ - " + "default-src 'self'; script-src 'self'; object-src 'none'; style-src 'self'; font-src 'self' data:; base-uri 'none'; form-action 'none';", ) .attr('http-equiv', 'Content-Security-Policy') head.meta.attr('charset', 'utf-8') - head - .meta - .attr('name', 'viewport') - .attr('content', 'width=device-width, initial-scale=1.0') + head.meta.attr('name', 'viewport').attr( + 'content', + 'width=device-width, initial-scale=1.0', + ) head .link @@ -132,13 +128,10 @@ fn head(config: ref Config, page: ref Page) -> html.Element { .attr('href', link_from(page, '/favicon.ico')) .attr('type', 'image/x-icon') - head - .script - .attr('src', link_from(page, '/js/main.js')) - .attr('defer', 'defer') + head.script.attr('src', link_from(page, '/js/main.js')).attr('defer', 'defer') head.add(link(link_from(page, '/css/reset.css'), rel: 'stylesheet')) - head.add(link(link_from(page, '/css/icons.css'), rel: 'stylesheet')) + head.add(link(link_from(page, '/css/icons.css'), rel: 'stylesheet')) head.add(link(link_from(page, '/css/main.css'), rel: 'stylesheet')) head.add(link(config.canonical_url(page), rel: 'canonical')) head.title.text(page.title) @@ -148,8 +141,8 @@ fn head(config: ref Config, page: ref Page) -> html.Element { fn header(config: ref Config, page: ref Page) -> html.Element { let root = html.Element.new('div') - root.attr('class', 'top-bar').header.attr('class', 'grid').with fn (h) { - h.div.attr('class', 'logo').with fn (logo) { + root.attr('class', 'top-bar').header.attr('class', 'grid').with(fn (h) { + h.div.attr('class', 'logo').with(fn (logo) { logo .img .attr('src', link_from(page, '/images/logo.png')) @@ -157,27 +150,30 @@ fn header(config: ref Config, page: ref Page) -> html.Element { .attr('width', '24') logo.span.text(config.title) - } + }) - h.div.attr('class', 'expand-menus').with fn (div) { + h.div.attr('class', 'expand-menus').with(fn (div) { div.add(toggle_menu('.top-bar nav', 'Show menu', 'Hide menu')) div.add(toggle_menu('.page aside.left', 'Show chapters', 'Hide chapters')) - } + }) - h.nav.ul.with fn (ul) { - config.menu.items.iter.each fn (pair) { - let item = - match pair.value.opt(0) { case Some(v) -> v, case _ -> return } + h.nav.ul.with(fn (ul) { + config.menu.items.iter.each(fn (pair) { + let item = match pair.value.opt(0) { + case Some(v) -> v + case _ -> return + } - ul.li.a.attr('href', link_from(page, item.url)).with fn (a) { + ul.li.a.attr('href', link_from(page, item.url)).with(fn (a) { a.text(pair.key) + if page.url.starts_with?(item.parent_url) or page.url == item.url { a.attr('class', 'current') } - } - } - } - } + }) + }) + }) + }) root } @@ -191,54 +187,54 @@ fn container( } fn pub home(config: ref Config, page: Page) -> html.Document { - let doc = html.Document.html('en') fn (html) { + let doc = html.Document.html('en', fn (html) { html.add(head(config, page)) - html.body.with fn (body) { + html.body.with(fn (body) { body.add(header(config, page)) - container(body, 'page home') fn (div) { + container(body, 'page home', fn (div) { home_sidebar(config, div, page) content(config.menu, page, div) - } - } - } + }) + }) + }) doc } fn pub page(config: ref Config, page: Page) -> html.Document { - let doc = html.Document.html('en') fn (html) { + let doc = html.Document.html('en', fn (html) { html.add(head(config, page)) - html.body.with fn (body) { + html.body.with(fn (body) { body.add(header(config, page)) - container(body, 'page') fn (div) { + container(body, 'page', fn (div) { sidebar(config, div, page) content(config.menu, page, div) - } - } - } + }) + }) + }) doc } fn pub missing(config: ref Config, page: Page) -> html.Document { - html.Document.html('en') fn (html) { + html.Document.html('en', fn (html) { html.add(head(config, page)) - html.body.with fn (body) { + html.body.with(fn (body) { body.add(header(config, page)) - container(body, 'missing-page') fn (div) { - div.article.with fn (article) { - article.header.with fn (h) { - h - .img - .attr('src', link_from(page, '/images/404.gif')) - .attr('height', '255') + container(body, 'missing-page', fn (div) { + div.article.with(fn (article) { + article.header.with(fn (h) { + h.img.attr('src', link_from(page, '/images/404.gif')).attr( + 'height', + '255', + ) h.h1.text(page.title) - } + }) article.append(page.to_html(filters(config.menu, page))) - } - } - } - } + }) + }) + }) + }) } diff --git a/docs/src/docs/menu.inko b/docs/src/docs/menu.inko index 7c3c7c381..2acde65cf 100644 --- a/docs/src/docs/menu.inko +++ b/docs/src/docs/menu.inko @@ -1,22 +1,21 @@ -import markdown.(split_front_matter) -import std.clone.Clone -import std.fs.file.ReadOnlyFile -import std.fs.path.Path -import std.json.Json -import wobsite.(Files, FrontMatter) -import wobsite.url.(file_url) +import markdown (split_front_matter) +import std.clone (Clone) +import std.fs.file (ReadOnlyFile) +import std.fs.path (Path) +import std.json (Json) +import wobsite (Files, FrontMatter) +import wobsite.url (file_url) fn parse_front_matter(path: ref Path) -> Result[FrontMatter, String] { let bytes = ByteArray.new - try ReadOnlyFile - .new(path) - .then fn (f) { f.read_all(bytes) } - .map_error fn (e) { "failed to read {path}: {e}" } + try ReadOnlyFile.new(path.clone).then(fn (f) { f.read_all(bytes) }).map_error( + fn (e) { 'failed to read ${path}: ${e}' }, + ) - FrontMatter - .parse(split_front_matter(bytes.into_string).0) - .map_error fn (e) { "failed to parse the front matter of {path}: {e}" } + FrontMatter.parse(split_front_matter(bytes.into_string).0).map_error(fn (e) { + 'failed to parse the front matter of ${path}: ${e}' + }) } class Item { @@ -33,7 +32,7 @@ class Item { impl Clone[Item] for Item { fn pub clone -> Item { - Item { @title = @title, @url = @url } + Item(title: @title, url: @url) } } @@ -41,16 +40,13 @@ class Menu { let @items: Map[String, Array[Item]] let @titles: Map[String, String] - fn static parse( - source: ref Path, - path: ref Path, - ) -> Result[Menu, String] { + fn static parse(source: ref Path, path: ref Path) -> Result[Menu, String] { let bytes = ByteArray.new try ReadOnlyFile - .new(path) - .then fn (f) { f.read_all(bytes) } - .map_error fn (e) { e.to_string } + .new(path.clone) + .then(fn (f) { f.read_all(bytes) }) + .map_error(fn (e) { e.to_string }) let root = match Json.parse(bytes) { case Ok(Object(map)) -> map @@ -61,7 +57,7 @@ class Menu { let titles = Map.new let items = Map.new - try root.into_iter.try_each fn (pair) { + try root.into_iter.try_each(fn (pair) { let key = pair.key let val = match pair { case { @value = Array(v) } -> v @@ -70,7 +66,7 @@ class Menu { let values = [] - try val.into_iter.try_each fn (val) { + try val.into_iter.try_each(fn (val) { let rel = match val { case String(v) -> v case _ -> throw 'each array value must be a string' @@ -81,29 +77,29 @@ class Menu { let url = file_url(source, path) titles.set(url, front.title) - values.push(Item { @title = front.title, @url = url }) + values.push(Item(title: front.title, url: url)) Result.Ok(nil) - } + }) items.set(key, values) Result.Ok(nil) - } + }) - Result.Ok(Menu { @items = items, @titles = titles }) + Result.Ok(Menu(items: items, titles: titles)) } } impl Clone[Menu] for Menu { fn pub clone -> Menu { - Menu { - @items = @items.iter.reduce(Map.new) fn (map, pair) { + Menu( + items: @items.iter.reduce(Map.new, fn (map, pair) { map.set(pair.key, pair.value.clone) map - }, - @titles = @titles.iter.reduce(Map.new) fn (map, pair) { + }), + titles: @titles.iter.reduce(Map.new, fn (map, pair) { map.set(pair.key, pair.value) map - } - } + }), + ) } } diff --git a/docs/src/docs/url.inko b/docs/src/docs/url.inko index d21b2a505..f1fd86bd8 100644 --- a/docs/src/docs/url.inko +++ b/docs/src/docs/url.inko @@ -1,11 +1,11 @@ -import wobsite.Page -import wobsite.url.(relative_to_absolute) +import wobsite (Page) +import wobsite.url (relative_to_absolute) fn link_from(page: ref Page, to: String) -> String { if page.url == '/' { to.strip_prefix('/') } else { - let mut steps = page.url.split('/').select fn (v) { v != '' }.count + let mut steps = page.url.split('/').select(fn (v) { v != '' }).count let to_abs = to.starts_with?('/') # The source/current URLs are directories (e.g. /foo/bar is in fact @@ -13,10 +13,10 @@ fn link_from(page: ref Page, to: String) -> String { # test, the URL is ../test instead of ../../test. if steps > 1 and to_abs.false? { steps -= 1 } - let up = String.join(0.until(steps).iter.map fn (_) { '..' }, '/') + let up = String.join(0.until(steps).iter.map(fn (_) { '..' }), '/') let sep = if to_abs { '' } else { '/' } - "{up}{sep}{to}" + '${up}${sep}${to}' } } diff --git a/docs/src/main.inko b/docs/src/main.inko index 2fb4d0ef9..0669b1fc8 100644 --- a/docs/src/main.inko +++ b/docs/src/main.inko @@ -1,15 +1,15 @@ -import docs.config.Config +import docs.config (Config) import docs.layouts -import wobsite.Site +import wobsite (Site) class async Main { fn async main { - Site.build fn (site) { + Site.build(fn (site) { # Each page needs this data, so we panic if we can't parse it as we can't # build the site without it. let conf = match Config.new(site.files.source) { case Ok(v) -> v - case Error(e) -> panic("failed to set up the configuration: {e}") + case Error(e) -> panic('failed to set up the configuration: ${e}') } site.copy('*.ico') @@ -20,29 +20,29 @@ class async Main { site.copy('*.css') site.copy('*.js') - site.page('/index.md', index: false) fn { + site.page_without_index('/index.md', fn { recover { let conf = conf.clone fn move (_, page) { Result.Ok(layouts.home(conf, page)) } } - } + }) - site.page('/404.md', index: false) fn { + site.page_without_index('/404.md', fn { recover { let conf = conf.clone fn move (_, page) { Result.Ok(layouts.missing(conf, page)) } } - } + }) - site.page('/*/*.md', index: true) fn { + site.page('/*/*.md', fn { recover { let conf = conf.clone fn move (_, page) { Result.Ok(layouts.page(conf, page)) } } - } - } + }) + }) } }