Hooks page
Generate the hooks page.
fs = require 'fs'
{Transform} = require 'stream'
Promise = require 'bluebird'
DoxPage = require '.'
module.exports = class DoxPageHooks extends DoxPage
Map hooks to source files.
buildHookMap: (transforms) ->
hookMap = {}
for key in ['invocations', 'implementations']
for transform in transforms
for item in transform[key]
((hookMap[item] ?= {})[key] ?= []).push transform.stream.file
return hookMap
Load hook templates.
hookTemplates: (hooks) ->
templates = {}
promises = for hook in hooks
do (hook) -> new Promise (resolve, reject) ->
TODO: Dynamic hook locations.
fs.readFile "packages/truss-dox/docs/hook/#{
hook
}.md", (error, output) ->
if error?
return reject error if error.code isnt 'ENOENT'
console.warn "Missing template for #{hook}..."
templates[hook] = output
resolve()
Promise.all(promises).then -> templates
transformsOutput: (transforms) ->
self = this
wordingFor =
implementation: 'implements'
invocation: 'invoke'
hookMap = @buildHookMap transforms
@hookTemplates(hooks = Object.keys hookMap).then (templates) ->
render = ''
for hook in hooks.sort((l, r) -> if l < r then -1 else 1)
Hook name.
render += "## #{hook}\n\n"
Hook template description.
render += templates[hook] + '\n\n' if templates[hook]
Output the i(mplement|nvoc)ations.
for key in ['implementation', 'invocation']
continue unless hookMap[hook][pluralKey = "#{key}s"]?
render += '<div class="admonition note">\n'
count = hookMap[hook][pluralKey].length
render += " <p class=\"admonition-title\">#{count} #{key}"
render += 's' if count > 1
render += '</p>\n'
render += ' <table>\n'
Output each i(mplement|nvoc)ation.
instances = for file, index in hookMap[hook][pluralKey]
sourceLink = self.linkToSource file
"""
<tr class="#{if index % 2 then 'odd' else 'even'}\">
<td>
<a href="../source/#{sourceLink}">#{file}</a>
</td>
<td align="right">
<a href="../source/#{sourceLink}##{wordingFor[key]}-hook-#{self.uniqueId sourceLink, hook}">#{key}</a>
</td>
</tr>
""".split('\n').map((e) -> " #{e}").join('\n')
render += instances.join '\n'
render += '\n </table>\n'
render += '</div>'
render += '\n\n'
return render
transformForStream: (stream) -> class HookTransform extends Transform
constructor: (@processor, @stream) ->
super null
@implementations = []
@invocations = []
_transform: (chunk, encoding, done) ->
line = chunk.toString 'utf8'
if matches = line.match /^\s*# #### Implements hook `([^`]+)`/
@implementations.push matches[1]
if matches = line.match /^\s*# #### Invoke hook `([^`]+)`/
@invocations.push matches[1]
done()