/**
- A tool to create
readme.md files based on the configuration from a .readme.json file and TypeDoc Markdown output.
- The example configuration file used to generate this documentation:
- @include [.readme.json]
- Unit tests:
- @include [test/readme.test.js]
- @module
*/
import { mkdirSync, readFileSync, writeFileSync } from 'fs'
import { dirname, join } from 'path'
import { js_on_parse } from './js_on_parse.js'
import { scan_dirs } from './scan_dirs.js'
/**
- Handler that reads the contents of the specified file.
- @param {string} path
- @returns {string}
*/
export const read_file = path => readFileSync(path, 'utf8').toString().replace(/\r/g, '').trim()
/**
- Helper that merge and fixes JavaScript source code documentation generated by the TypeDoc tool with typedoc-plugin-markdown plugin.
- @param {{
- defined_in?: {
-
prefix?: string;
-
separator?: string;
-
suffix?: string;
- };
- path: string;
- }} config
- @returns {string}
*/
export const fix_typedoc = config => {
let { defined_in, path } = config
defined_in = defined_in ?? {}
defined_in.prefix = defined_in.prefix ?? ''
defined_in.separator = defined_in.separator ?? ''
defined_in.suffix = defined_in.suffix ?? ''
const PATH_INTERFACES = join(path, 'interfaces')
const PATH_MODULES = join(path, 'modules')
const lines_by_path = {}
const interface_hash = {}
const out_lines = []
const toc_push = (match, name) => {
out_lines.push(- [${name}](#module-${name.replace(/\\/g, '').toLowerCase()}))
return match
}
const register_interface = (match, name) => {
interface_hash[name.replace(/\/g, '').replace(/<.*>$/, '')] =
'interface-' + name.replace(/[<\>]/g, '').toLowerCase()
return match
}
const interface_link_replacer = (_, basename) => lines_by_path[join(PATH_INTERFACES, basename)].join('\n')
const defined_in_replacer = (line, index, lines, match, basename, line_no) =>
lines[index - 2].match(/^#+ Defined in$/)
? [${basename}:${line_no}](https://github.com/jackens/jc/blob/master/src/${basename}#L${line_no})
: match
const name_to_hash_replacer = (_, name) =>
[\${name}`](#${interface_hash[name] ?? name.toLowerCase()})`
const include_tag_replacer = (match, path2) => {
const lang = path2.match(/.(\w+)$/)?.[1] ?? ''
return ['' + lang, read_file(path2), ''].join('\n')
}
scan_dirs(PATH_INTERFACES, PATH_MODULES).filter(path2 => path2.endsWith('.md')).sort().forEach(path2 => {
lines_by_path[path2] = read_file(path2).split('\n').map((line, index, lines) => line
.replace(/^,.$/, '') // workaround https://github.com/TypeStrong/typedoc/issues/1913
.replace(/^#+ (Defined in|Index signature|Parameters|Returns|Type parameters|Type declaration)$/, '$1:')
.replace(/^(#+ )/, path2.startsWith(PATH_INTERFACES) ? '###$1' : '#$1')
.replace(/^#{7,} (.)$/, '$1:')
.replace(/^#+ Module: (.+)$/, toc_push)
.replace(/^#+ Interface: (.+)$/, register_interface)
.replace(/^(Ƭ|▪|▸|•) /, '')
.replace(/^[.+?](../modules/.+?.md)..+$/, '')
.replace(/^- [.+?](../interfaces/(.+?.md))$/, interface_link_replacer)
.replace(/^(\w+.js):(\d+)$/, defined_in_replacer.bind(null, line, index, lines))
.replace(/[(\w+?)]([#./\w]*?)/g, name_to_hash_replacer)
.replace(/^**include** [(.+?)]$/g, include_tag_replacer)
)
})
out_lines.push('')
Object.keys(lines_by_path)
.filter(path2 => path2.startsWith(PATH_MODULES))
.sort()
.forEach(path2 => out_lines.push(...lines_by_path[path2], ''))
return out_lines.join('\n')
}
/**
- Helper that writes an array of lines to the specified file.
- @param {{
- lines: string[];
- path: string;
- }} config
- @returns {string}
*/
export const write_file = config => {
const { lines, path } = config
try {
mkdirSync(dirname(path), { recursive: true })
} catch {}
const data = lines.join('\n')
writeFileSync(path, data)
return data
}
js_on_parse(readFileSync('.readme.json', 'utf8').toString(), { read_file, write_file, fix_typedoc })