1 | path = require('path')
|
2 | fs = require('fs')
|
3 | _ = require('lodash')
|
4 |
|
5 | HbHelper = require('@resin.io/doxx-handlebars-helper')
|
6 | { walkFiles, walkTree } = require('@resin.io/doxx-utils')
|
7 |
|
8 | LunrIndex = require('./lunr-index')
|
9 | Dicts = require('./dictionaries')
|
10 | { tokenize } = require('metalsmith-dynamic').util
|
11 |
|
12 | { extractTitleFromText, slugify, replacePlaceholders,
|
13 | filenameToRef, refToFilename, getValue } = require('./util')
|
14 |
|
15 | module.exports = (config, navTree) ->
|
16 | dicts = Dicts(config)
|
17 | exports = {}
|
18 |
|
19 | exports.skipPrivate = walkFiles (file, files) ->
|
20 | if path.parse(file).name.match(/^_/)
|
21 | delete files[file]
|
22 |
|
23 | fileByRef = {}
|
24 |
|
25 | exports.populateFileMeta = walkFiles (file, files) ->
|
26 | obj = files[file]
|
27 | _.assign(obj, getValue(config.metaExtra, file, obj))
|
28 | title = obj.title or extractTitleFromText(obj.contents.toString())
|
29 | excerpt = obj.excerpt
|
30 | obj.title = HbHelper.render(title, obj)
|
31 | obj.excerpt = HbHelper.render(excerpt, obj)
|
32 | [ obj.ref, obj.ext ] = filenameToRef(file)
|
33 | fileByRef[obj.ref] = obj
|
34 |
|
35 | exports.buildSearchIndex = ->
|
36 | console.log('Building search index...')
|
37 | searchIndex = LunrIndex.create()
|
38 |
|
39 | return (files, metalsmith, done) ->
|
40 | for file of files
|
41 | obj = files[file]
|
42 | searchIndex.add
|
43 | id: obj.ref
|
44 | title: obj.title
|
45 | body: obj.contents.toString()
|
46 | indexFilePath = config.buildLunrIndex
|
47 | searchIndex.write indexFilePath, (err) ->
|
48 | throw err if err
|
49 | console.log('Successfully finished indexing.')
|
50 | done()
|
51 |
|
52 | navByRef = null
|
53 |
|
54 | exports.parseNav = ->
|
55 | setRefRec = (ref, node, remainingVariables) ->
|
56 | if not remainingVariables?.length
|
57 | return setRef(ref, node)
|
58 | [ nextVariable, remainingVariables... ] = remainingVariables
|
59 | for value in dicts.getValues(nextVariable)
|
60 | setRefRec(
|
61 | replacePlaceholders(ref, { "#{nextVariable}": value }),
|
62 | node,
|
63 | remainingVariables
|
64 | )
|
65 |
|
66 | setRef = (ref, node) ->
|
67 | return if not ref?
|
68 | if ref.indexOf('$') >= 0
|
69 | tokens = (t for t, i in tokenize(ref) when i % 2)
|
70 | setRefRec(ref, node, tokens)
|
71 | else
|
72 | navByRef[ref] = node
|
73 |
|
74 | setRefs = walkTree
|
75 | visitNode: (node) ->
|
76 | if node.level?
|
77 | setRef(node.ref, node)
|
78 |
|
79 | fixNavNodeTitleAndSetSlug = walkTree
|
80 | visitNode: (node) ->
|
81 | if node.level?
|
82 | node.title or= fileByRef[node.ref]?.title
|
83 | node.slug = slugify(node.title)
|
84 |
|
85 | addNavParents = walkTree
|
86 | visitNode: (node, parents) ->
|
87 | if node.level?
|
88 | node.parents = parents.concat(node)
|
89 | buildNextArgs: (node, parents) ->
|
90 | if node.level?
|
91 | [ parents.concat(node) ]
|
92 | else
|
93 | [ parents ]
|
94 |
|
95 | return (files, metalsmith, done) ->
|
96 | console.log('Parsing navigation...')
|
97 |
|
98 | fixNavNodeTitleAndSetSlug(navTree)
|
99 | addNavParents(navTree, [])
|
100 |
|
101 | navByRef = {}
|
102 | setRefs(navTree)
|
103 |
|
104 | console.log('Navigation parsed and indexed.')
|
105 | done()
|
106 |
|
107 | exports.serializeNav = ->
|
108 |
|
109 |
|
110 | removeBackRefs = walkTree
|
111 | visitNode: (node) ->
|
112 | delete node.parent
|
113 | delete node.parents
|
114 |
|
115 | return (files, metalsmith, done) ->
|
116 | removeBackRefs(navTree)
|
117 |
|
118 | filename = config.serializeNav
|
119 | fs.writeFile filename, JSON.stringify(navTree), (err) ->
|
120 | throw err if err
|
121 | console.log('Successfully serialized navigation tree.')
|
122 | done()
|
123 |
|
124 | exports.populateFileNavMeta = walkFiles (file, files) ->
|
125 | obj = files[file]
|
126 | { ref } = obj
|
127 | navNode = navByRef[ref]
|
128 |
|
129 | obj.$nav = nav =
|
130 | url: "/#{obj.ref}"
|
131 |
|
132 | parents = navNode?.parents
|
133 |
|
134 |
|
135 | if parents?
|
136 | nav.path = {}
|
137 | for node in parents
|
138 | nav.path[node.$id] = true
|
139 |
|
140 |
|
141 | obj.breadcrumbs = bc = parents?.map (node) ->
|
142 | node.title
|
143 |
|
144 | if navNode?.isDynamic
|
145 | nav.title = HbHelper.render(navNode.titleTemplate, obj)
|
146 | if bc?.length
|
147 | bc[bc.length - 1] = nav.title
|
148 | else
|
149 | nav.title = navNode?.title
|
150 |
|
151 | return exports
|