## 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 "" 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("
  • ", 1)[0] for item in html.split("\n
    " types_html[name] = "
    ", 1)[0] & "
    " 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
    ": if line.startswith " title=\"TYPES = ": types_line = line menu_line = i - 1 elif types_line != "": types_line &= line if "" 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 &"
    " while lines[body_line] != "
    ": lines.delete body_line lines.delete body_line for tname in types: var ids = types_html[tname].split "" 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)