aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authors-ol <s-ol@users.noreply.github.com>2020-03-03 15:56:23 +0000
committers-ol <s-ol@users.noreply.github.com>2020-03-05 10:36:33 +0000
commitb0f6006aa5514a6c3b6b105c791355cf9c366883 (patch)
tree09d19b698d1c6bc41c69e6dea5ffd90e6d88c1c2
parentrefactoring cyclic requires (diff)
downloadalive-b0f6006aa5514a6c3b6b105c791355cf9c366883.tar.gz
alive-b0f6006aa5514a6c3b6b105c791355cf9c366883.zip
add doc generator
-rw-r--r--Makefile17
-rw-r--r--docs/.gitignore1
-rw-r--r--docs/style.css78
-rw-r--r--extra/docs.moon45
-rw-r--r--extra/dom.moon66
-rw-r--r--extra/layout.moon78
6 files changed, 285 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..b1d7263
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,17 @@
+MODULES=$(wildcard lib/*.moon) lib/midi/launchctl.moon
+MODREFS=$(MODULES:lib/%.moon=docs/reference/%.html)
+
+.PHONY: docs clean
+
+docs: $(MODREFS) docs/reference/index.html
+
+docs/reference/%.html: lib/%.moon extra/docs.moon extra/layout.moon
+ @echo "building docs for $<"
+ @mkdir -p `dirname $@`
+ moon extra/docs.moon $@ module lib.$(*:/=.) $*
+
+docs/reference/index.html: $(MODREFS) extra/docs.moon extra/layout.moon
+ moon extra/docs.moon $@ reference $(MODULES)
+
+clean:
+ rm -rf docs/reference/*
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 0000000..2d19fc7
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1 @@
+*.html
diff --git a/docs/style.css b/docs/style.css
new file mode 100644
index 0000000..809ee05
--- /dev/null
+++ b/docs/style.css
@@ -0,0 +1,78 @@
+html {
+ margin: 0;
+ padding: 0;
+ background: #222222 center center fixed;
+ background-image: url("data:image/svg+xml,%3Csvg width='30' height='30' viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill-rule='evenodd'%3E%3Cg fill='%23606060' fill-opacity='0.4'%3E%3Cpath d='m7.5,9v12h4v-2h-2v-8h2V9Zm11,0v2h2v8h-2v2h4V9Z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
+}
+
+body {
+ margin: auto;
+ width: 640px;
+ background: #eeeeee;
+
+ font-family: 'Source Sans Pro', sans-serif;
+ color: #222222;
+}
+
+article {
+ padding: 3rem 2em 1em;
+}
+
+code {
+ font-family: 'Source Code Pro', monospace;
+}
+
+h2 {
+ margin: 0.5em 0 0.25em;
+}
+
+a {
+ color: inherit;
+}
+
+ul {
+ list-style: '- ';
+ margin: 0;
+ padding-left: 0.6em;
+}
+
+nav {
+ position: fixed;
+ width: inherit;
+ height: 4rem;
+ top: 0;
+ padding: 1em 2em 4px;
+ background: #eeeeee;
+ box-sizing: border-box;
+}
+
+nav div {
+ display: flex;
+ justify-content: space-around;
+
+ border-bottom: 1px solid #222222;
+ padding-bottom: 1em;
+}
+
+nav i {
+ flex: 1;
+}
+
+nav a {
+ margin-left: 1rem;
+}
+
+.def {
+ margin-top: 0.5rem;
+}
+
+.nest {
+ margin: 0.25rem 0.25rem 0 0;
+ padding-left: 0.75rem;
+ border-left: 1px solid #222222;
+}
+
+.nest > p {
+ margin: 0;
+ white-space: pre-wrap;
+}
diff --git a/extra/docs.moon b/extra/docs.moon
new file mode 100644
index 0000000..a8438cf
--- /dev/null
+++ b/extra/docs.moon
@@ -0,0 +1,45 @@
+import Value, Scope from require 'core'
+import render, write from require 'extra.layout'
+import section, h2, p, ul, li, a, code, r from require 'extra.dom'
+
+export OUT
+{ OUT, command } = arg
+
+write switch command
+ when 'module'
+ { _, _, module, name } = arg
+
+ name or= module
+ module = Scope.from_table require module
+
+ title: "#{name} module reference"
+ body: section {
+ h2 (code name), ' reference'
+ ul for key, res in pairs module.values
+ li render key, res.value
+ }
+
+ when 'reference'
+ title: 'reference index'
+ body: {
+ section {
+ id: 'modules'
+ h2 a "module index", href: '#modules'
+ p "These modules can be imported using #{r 'require'}, #{r 'import'} and " ..
+ "#{r 'import*'}."
+ ul for file in *arg[3,]
+ module = file\match '^lib/(.*)%.moon$'
+ li a (code module), href: "#{module}.html"
+ }
+ section {
+ id: 'builtins'
+ h2 a "builtins", href: '#builtins'
+ p "These definitions are automatically loaded into the global Scope of
+ every alive session."
+ ul for key, val in pairs require 'core.builtin'
+ li render key, Value.wrap val
+ }
+ }
+
+ else
+ error "unknown command '#{command}'"
diff --git a/extra/dom.moon b/extra/dom.moon
new file mode 100644
index 0000000..73dc743
--- /dev/null
+++ b/extra/dom.moon
@@ -0,0 +1,66 @@
+-- mmm.dom
+-- see https://mmm.s-ol.nu/meta/mmm.dom/
+
+-- ordered table iterator, for stable(r) renderers
+sort = (t, order_fn, only_strings) ->
+ with index = [k for k,v in pairs t when (not only_strings) or 'string' == type k]
+ table.sort index, order_fn
+
+-- ordered next(t)
+onext = (state, key) ->
+ state.i += state.step
+ { :t, :index, :i } = state
+
+ if key = index[i]
+ key, t[key]
+
+-- ordered pairs(t).
+-- order_fn is optional; see table.sort
+opairs = (t, order_fn, only_strings=false) ->
+ state = { :t, i: 0, step: 1, index: sort t, order_fn, only_strings }
+ onext, state, nil
+
+void_tags = { 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr' }
+void_tags = { t,t for t in *void_tags }
+
+element = (element) -> (...) ->
+ children = { ... }
+
+ -- attributes are last arguments but mustn't be a ReactiveVar
+ attributes = children[#children]
+ if 'table' == (type attributes) and not attributes.node
+ table.remove children
+ else
+ attributes = {}
+
+ b = "<#{element}"
+ for k,v in opairs attributes, nil, true
+ if k == 'style' and 'table' == type v
+ tmp = ''
+ for kk, vv in opairs v
+ tmp ..= "#{kk}: #{vv}; "
+ v = tmp
+ b ..= " #{k}=\"#{v}\""
+
+ -- if there is only one argument,
+ -- children can be in attributes table too
+ if #children == 0
+ children = attributes
+
+ for i,v in ipairs children
+ if 'string' != type v
+ print v
+ error "wrong type: #{type v}"
+ children[i] = '' unless v
+
+ if void_tags[element]
+ assert #children == 0, "void tag #{element} cannot have children!"
+ b .. ">"
+ else
+ b ..= ">" .. table.concat children, ''
+ b ..= "</#{element}>"
+ b
+
+setmetatable {}, __index: (name) =>
+ with val = element name
+ @[name] = val
diff --git a/extra/layout.moon b/extra/layout.moon
new file mode 100644
index 0000000..1a4ee7b
--- /dev/null
+++ b/extra/layout.moon
@@ -0,0 +1,78 @@
+-- render an ALV Value to a HTML string
+render = (name, value, prefix=nil) ->
+ import div, label, code, ul, li, i, a, p from require 'extra.dom'
+
+ id = if prefix then "#{prefix}/#{name}" else name
+ type = i value.type
+
+ content = switch value.type
+ when 'scope'
+ ul for k, result in pairs value!.values
+ li render k, result.value, id
+ when 'opdef', 'builtin'
+ p value!.doc
+ when 'num', 'str', 'bool'
+ code tostring value!
+
+ div {
+ :id, class: 'def'
+ label (a (code name), :id, href: "##{id}"), ' (', type, '):'
+ div content, class: 'nest'
+ }
+
+-- generate a relative link
+abs = (page) ->
+ assert OUT, "OUT needs to be set"
+ relative = assert (OUT\match '^docs/(.*)'), "unexpected output path"
+ _, depth = relative\gsub '/', '/'
+ up = string.rep '../', depth
+ "#{up}#{page}"
+
+-- link to a reference
+r = (name, page='') ->
+ import a, code from require 'extra.dom'
+ a (code name), href: "#{page}##{name}"
+
+spit = (file, str) ->
+ file = io.open file, 'w'
+ file\write str
+ file\close!
+
+-- layout and write a doc page
+-- opts:
+-- - title
+-- - body
+write = (opts) ->
+ import nav, div, span, b, code, i, a, article from require 'extra.dom'
+
+ navigation = nav div {
+ span (b 'alive'), ' ', (code 'v0.0'), ' documentation'
+ i!
+ a 'home', href: abs 'index.html'
+ a 'getting started', href: abs 'guide.html'
+ a 'reference', href: abs 'reference/index.html'
+ }
+ body = article opts.body
+
+ assert OUT, "OUT needs to be set"
+ spit OUT, "<!DOCTYPE html>
+<html>
+ <head>
+ <title>#{opts.title} - alive docs</title>
+ <link rel=\"stylesheet\" href=\"#{abs 'style.css'}\">
+ <style>
+
+ </style>
+ </head>
+ <body>
+ #{navigation}
+ #{body}
+ </body>
+</html>"
+
+
+{
+ :r
+ :render
+ :write
+}