126 lines
4.1 KiB
Nim
126 lines
4.1 KiB
Nim
|
|
|
|
## This program fixes the documentation putting the types in each module.
|
|
## At the moment, all types are in types.nim to allow cyclic definitions,
|
|
## and all members are public to allow access in the appropriate modules.
|
|
##
|
|
## We signal that we want to move types with the TYPES type, like this:
|
|
##
|
|
## when defined(nimdoc):
|
|
## type TYPES* = MyType1 | MyType2 | MyType3
|
|
##
|
|
## Furthermore, we hide all members that have "## private" in their docs.
|
|
##
|
|
## All of this is a hacky workaround that we hope won't be necessary
|
|
## in the future.
|
|
##
|
|
## Usage: nim r fixdocs.nim htmldocs/*
|
|
|
|
import sugar
|
|
import os, strutils, sequtils, tables, algorithm, strformat
|
|
|
|
|
|
var types_menu: Table[string, string]
|
|
var types_html: Table[string, string]
|
|
|
|
proc strip_privates(s: string): string =
|
|
var lines: seq[string]
|
|
var private = false
|
|
for line in s.split '\n':
|
|
if ("*" in line and ":" in line) or "</pre>" in line:
|
|
private = false
|
|
if "## private" in line:
|
|
private = true
|
|
if not private:
|
|
lines.add line
|
|
return lines.join "\n"
|
|
|
|
|
|
for f in os.commandLineParams():
|
|
if f.rsplit("/", 1)[^1] == "types.html":
|
|
let html = readFile(f)
|
|
for item in html.split("<li><a class=\"reference\"")[1 ..< ^0]:
|
|
let name = item.split({'"','#'}, 3)[2]
|
|
types_menu[name] = "<li><a class=\"reference\"" & item.split("</ul>", 1)[0]
|
|
for item in html.split("\n<div id=\"")[1 ..< ^0]:
|
|
let name = item.split('"',1)[0]
|
|
# TODO: check if RST can produce a bare "\n</div>"
|
|
types_html[name] = "<div id=\"" & item.split("\n</div>", 1)[0] & "</div>"
|
|
|
|
var type_to_module: Table[string, string]
|
|
|
|
for f in os.commandLineParams():
|
|
if not f.endswith ".html":
|
|
continue
|
|
var types: seq[string]
|
|
var lines = readFile(f).split("\n")
|
|
var menu_line = 0
|
|
var last_menu_line = 0
|
|
var types_line = ""
|
|
for i,line in lines:
|
|
# if "reference reference-toplevel" in line and line.endswith ">Types</a>":
|
|
if line.startswith " title=\"TYPES = ":
|
|
types_line = line
|
|
menu_line = i - 1
|
|
elif types_line != "":
|
|
types_line &= line
|
|
if "</a>" in types_line:
|
|
types = types_line.split({'"','='})[3].split({'|',' '}).filterIt it != ""
|
|
last_menu_line = i
|
|
break
|
|
if types.len == 0:
|
|
continue
|
|
|
|
for tname in types:
|
|
type_to_module[tname] = f.rsplit("/", 1)[^1].split('.')[0]
|
|
|
|
types.sort(order = Descending)
|
|
|
|
assert menu_line != 0
|
|
|
|
# types_id is usually "TYPES" but for some reason it's "TYPES_2" sometimes,
|
|
# so we'll extract the id from the href before we delete it
|
|
let types_id = lines[menu_line].rsplit("#",1)[1].split("\"")[0]
|
|
for i in menu_line .. last_menu_line:
|
|
lines.delete menu_line
|
|
|
|
for tname in types:
|
|
var parts = types_menu[tname].split('"')
|
|
parts[5] = parts[5].strip_privates
|
|
lines.insert(parts.join("\""), menu_line)
|
|
|
|
var body_line = lines.find &"<div id=\"{types_id}\">"
|
|
while lines[body_line] != "</div>":
|
|
lines.delete body_line
|
|
lines.delete body_line
|
|
|
|
for tname in types:
|
|
var ids = types_html[tname].split "<span class=\"Identifier\">"
|
|
lines.insert(types_html[tname].strip_privates, body_line)
|
|
|
|
writeFile(f, lines.join "\n")
|
|
|
|
dump type_to_module
|
|
|
|
for f in os.commandLineParams():
|
|
let is_html = f.endswith ".html"
|
|
let is_idx = f.endswith ".idx"
|
|
if not (is_html or is_idx):
|
|
continue
|
|
var sep = if is_html: "\"" else: "\t"
|
|
let is_index = f.rsplit("/", 1)[^1] == "theindex.html"
|
|
let contents = readFile(f)
|
|
var changed = contents
|
|
for tname, module in type_to_module:
|
|
changed = changed.replace(
|
|
&"{sep}types.html#{tname}{sep}",
|
|
&"{sep}{module}.html#{tname}{sep}")
|
|
if is_index:
|
|
for seps in ["\"\"", "><"]:
|
|
changed = changed.replace(
|
|
&"{seps[0]}types: {tname}{seps[1]}",
|
|
&"{seps[0]}{module}: {tname}{seps[1]}")
|
|
if contents != changed:
|
|
writeFile(f, changed)
|
|
|