UNPKG

6.27 kBMarkdownView Raw
1# mako-tree
2
3> The build tree structure used internally by [mako](https://github.com/makojs/core)
4
5[![npm version](https://img.shields.io/npm/v/mako-tree.svg)](https://www.npmjs.com/package/mako-tree)
6[![build status](https://img.shields.io/travis/makojs/tree.svg)](https://travis-ci.org/makojs/tree)
7
8## Overview
9
10When working with mako build hooks, the first 2 arguments will be the current `file` and the build
11`tree` respectively. Currently, both of those APIs are contained in this module, as they tightly
12coupled and don't make much sense on their own. (at least at the current time)
13
14Throughout the "analyze" phase, a tree is being built up, starting from the list of entry files.
15Each file being processed adds any direct dependencies, which will then recursively be processed
16to find more dependencies. Each vertex in the graph corresponds to some sort of input file.
17
18During the "build" phase, the tree _may_ be trimmed down, such as the case where the entire
19dependency chain for a JS file will be combined into a single output file. By the end of the build,
20each vertex in the graph corresponds to an output file.
21
22## API
23
24> As mako continues to be developed and evolve, some documentation and guides dedicated to plugin
25authors will surface. For now, the following is purely the API available to both the `file` and
26`tree` parameters in plugins/hooks.
27
28The `Tree` constructor (documented below) is the primary export for the module. It must be used
29with the `new` keyword.
30
31```js
32var Tree = require('mako-tree');
33var tree = new Tree();
34```
35
36### Tree() *(constructor)*
37
38Each instance represents a build tree. Internally, a graph is used to manage the relationships
39between all the files being tracked.
40
41**NOTE:** All paths are assumed to be absolute, this library makes no attempt to set a base/root
42directory and maintain relative paths.
43
44### Tree#hasFile(location)
45
46Returns a `Boolean` reflecting if the file at the given `location` exists in this tree.
47
48### Tree#addFile(location)
49
50Adds a file at the given `location` to the tree, if it is not already present, and returns the
51corresponding `File` instance.
52
53### Tree#getFile(location)
54
55Returns the `File` instance for the file at the given `location`. It is assumed to already be part
56of the graph, and will throw an error if not found.
57
58### Tree#removeFile(location)
59
60Removes the file at the given `location` from the tree. To successfully remove a file, it must not
61be depended on by another file. This is mostly a plumbing function, and plugin authors are likely
62going to use `removeDependency()` instead.
63
64### Tree#isSource(location)
65
66Returns a `Boolean` telling whether or not the file at `location` is an entry file. (in other
67words, is not a dependency)
68
69### Tree#getEntries([from])
70
71Returns an `Array` of all the entry files in this graph. (in other words, files that are at the
72end of the dependency chains)
73
74If `from` is provided, the returned list will only include entries that are reachable from that
75specified file.
76
77### Tree#hasDependency(parent, child)
78
79Returns a `Boolean` reflecting if the dependency relationship between `parent` and `child` already
80exists in the tree.
81
82### Tree#addDependency(parent, child)
83
84Adds a new dependency relationship to the graph setting `parent` as depending on `child`. If
85`child` is not already part of the tree, it will be added. (however, if `parent` is not in the tree,
86that is assumed to be an error) This will return the `File` instance for the `child` file.
87
88### Tree#removeDependency(parent, child)
89
90Removes the specified dependency relationship, basically saying that `parent` no longer depends on
91`child`)
92
93**NOTE:** If no other files depend on `child`, it will be removed from the tree. This allows
94plugins to only concern themselves with the relationships they are aware of, leaving the overall
95tree management to mako.
96
97### Tree#moveDependency(from, to, child)
98
99A helper for moving a dependency on `child` from one parent to another, which is more explicit than
100manually adding and removing the dependency links. (which must be done in the right order due to
101the automatic cleanup behavior of removing dependencies)
102
103An example use case: after inlining a tree of CSS files, the images/fonts/etc will need to be moved
104from being dependencies of the input files, to the single output file.
105
106### Tree#dependenciesOf(file, [recursive])
107
108Returns an `Array` of files that are dependencies of the given `file`.
109
110By default, it will only return the direct descendants, but adding `recursive` will return a flat
111list of all the files **down** the entire dependency chain.
112
113### Tree#dependantsOf(file, [recursive])
114
115Returns an `Array` of files that depend on the given `file`.
116
117By default, it will only return the direct ancestors, but adding `recursive` will return a flat
118list of all the files **up** the entire dependency chain.
119
120### Tree#topologicalOrder()
121
122Returns an `Array` of files that can be processed in an order that respects all the dependencies.
123
124### File(location) *(constructor)*
125
126Each instance represents a file in the overall build.
127
128### File#path
129
130The absolute path to where this file exists on disk.
131
132### File#type
133
134The current file type associated with this file. This value is used to determine what plugins/hooks
135need to be invoked at various stages.
136
137**NOTE:** plugins can modify this value if their work changes the file type. (such as compiling
138`.coffee` into `.js`)
139
140### File#contents
141
142This holds the current contents of the file. When first read, this property should be set, and
143subsequent changes to the source code should apply to this property.
144
145**NOTE:** must be set by a plugin.
146
147### File#output
148
149The absolute path to where this file should be written on disk.
150
151**NOTE:** must be set by a plugin.
152
153### File#isEntry()
154
155Short-hand for `tree.isEntry(file.path)`.
156
157### File#hasDependency(child)
158
159Short-hand for `tree.hasDependency(file.path, child)`.
160
161### File#addDependency(child)
162
163Short-hand for `tree.addDependency(file.path, child)`.
164
165### File#removeDependency(child)
166
167Short-hand for `tree.removeDependency(file.path, child)`.
168
169### File#dependencies([recursive])
170
171Short-hand for `tree.dependenciesOf(file.path, recursive)`.
172
173### File#dependants([recursive])
174
175Short-hand for `tree.dependantsOf(file.path, recursive)`.