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