UNPKG

4.19 kBtext/coffeescriptView Raw
1path = require('path')
2fs = require('fs')
3_ = require('lodash')
4
5HbHelper = require('@resin.io/doxx-handlebars-helper')
6{ walkFiles, walkTree } = require('@resin.io/doxx-utils')
7
8LunrIndex = require('./lunr-index')
9Dicts = require('./dictionaries')
10{ tokenize } = require('metalsmith-dynamic').util
11
12{ extractTitleFromText, slugify, replacePlaceholders,
13 filenameToRef, refToFilename, getValue } = require('./util')
14
15module.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 # needed because of
109 # https://github.com/superwolff/metalsmith-layouts/issues/83
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 # set nav path
135 if parents?
136 nav.path = {}
137 for node in parents
138 nav.path[node.$id] = true
139
140 # set breadcrumbs
141 obj.breadcrumbs = bc = parents?.map (node) ->
142 node.title
143 # TODO: this logic is twisted and should be improved
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