1 | fs = require('fs')
|
2 | _ = require('lodash')
|
3 | { walkTree } = require('@resin.io/doxx-utils')
|
4 |
|
5 | fixLinks = walkTree
|
6 | visitNode: (node) ->
|
7 | if node.level? and not node.link
|
8 | if not node.children?.length
|
9 | throw new Error("No link and no child lines. #{node.raw}")
|
10 | node.isGateway = true
|
11 | node.link = node.children[0].link
|
12 |
|
13 | calcRefs = walkTree
|
14 | visitNode: (node) ->
|
15 | { link } = node
|
16 | if link and link[0] is '/'
|
17 | node.ref = link[1..]
|
18 |
|
19 | if node.level? and not node.ref? and not node.title
|
20 | throw new Error("No title for external link node. #{node.raw}")
|
21 |
|
22 | calcIds = (rootNode, rootId) ->
|
23 | setId = (node, id) ->
|
24 | node.$id = id
|
25 | if node.children
|
26 | for child, i in node.children
|
27 | setId(child, "#{id}.#{i + 1}")
|
28 | setId(rootNode, rootId)
|
29 |
|
30 | exports.parse = (config) ->
|
31 | lines = fs.readFileSync(config.parseNav)
|
32 | .toString()
|
33 | .split('\n')
|
34 | .map (s) -> s.trimRight()
|
35 | .filter (s) -> s and not s.match(/\s*#/)
|
36 | .map (s) ->
|
37 | [ pad, line ] = s.match(/^(\s*)(.*)$/)[1..]
|
38 | if pad.length % 2 or not pad.match(/^ *$/)
|
39 | throw new Error("Wrong indent! Must be even and spaces-only. #{s}")
|
40 | return { level: pad.length / 2, raw: line }
|
41 | .map ({ level, raw }) ->
|
42 | [ title, skip, link ] = raw.match(/^([^\[]+)?(\[(.+)\])?$/)[1..]
|
43 | node = { level, raw, title, link }
|
44 | if link?.match(/\$/)
|
45 | node.isDynamic = true
|
46 | linkReParts = link.split(/\$[\w_]+/).map(_.escapeRegExp)
|
47 | node.linkRe = new RegExp('^' + linkReParts.join('.*') + '$')
|
48 | if not title
|
49 | throw new Error("Dynamic pages must specify the title. #{raw}")
|
50 | titleParts = title.split(/\s*~\s*/)
|
51 | node.title = titleParts[0]
|
52 | node.titleTemplate = titleParts[1] or titleParts[0]
|
53 | return node
|
54 |
|
55 | trees = []
|
56 | currentNode = null
|
57 |
|
58 | for line in lines
|
59 | if not currentNode?
|
60 | if line.level isnt 0
|
61 | throw new Error("First line must have no indent. #{line.raw}")
|
62 |
|
63 | trees.push(line)
|
64 | else
|
65 | if line.level > currentNode.level + 1
|
66 | throw new Error("Indent too big. #{line.raw}")
|
67 |
|
68 | while currentNode and line.level <= currentNode.level
|
69 | currentNode = currentNode.parent
|
70 | if not currentNode
|
71 | trees.push(line)
|
72 | else
|
73 | currentNode.children ?= []
|
74 | currentNode.children.push(line)
|
75 | line.parent = currentNode
|
76 |
|
77 | currentNode = line
|
78 |
|
79 | result =
|
80 | level: null
|
81 | ref: undefined
|
82 | link: null
|
83 | title: '<root>'
|
84 | raw: '<root>'
|
85 | children: trees
|
86 |
|
87 | fixLinks(result)
|
88 | calcRefs(result)
|
89 | calcIds(result, '$0')
|
90 |
|
91 | return result
|
92 |
|
93 | ppNode = walkTree
|
94 | visitNode: (node, indent = '') ->
|
95 | title = node.title or '(No title)'
|
96 | link = if node.link then "[#{node.link}]" else ''
|
97 | console.log "#{indent}|--#{title}#{link}"
|
98 | buildNextArgs: (node, indent = '') ->
|
99 | [ indent + '| ' ]
|
100 |
|
101 | exports.pp = (tree) ->
|
102 | ppNode(tree)
|
103 |
|
104 | exports.serialize = (tree, path) ->
|
105 | return
|