precedent 1.0.6 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/.config/code-server/config.yaml +4 -0
  2. package/.config/configstore/update-notifier-npm-check-updates.json +4 -0
  3. package/.config/configstore/update-notifier-npm.json +4 -0
  4. package/.vscode/launch.json +46 -0
  5. package/Dockerfile_LUXURYCode +69 -0
  6. package/{harness/Debug.js → debug/Harness.js} +0 -0
  7. package/dist/precedent.js +317 -0
  8. package/dist/precedent.min.js +39 -0
  9. package/dist/precedent.min.js.map +1 -0
  10. package/gulpfile.js +73 -58
  11. package/package.json +35 -16
  12. package/source/Precedent-Browser-Shim.js +8 -6
  13. package/source/StringParser.js +1 -1
  14. package/source/WordTree.js +7 -7
  15. package/test/Precedent_tests.js +106 -0
  16. package/test.js +1 -0
  17. package/.c9/.nakignore +0 -17
  18. package/.c9/metadata/tab0 +0 -1
  19. package/.c9/metadata/tab3 +0 -1
  20. package/.c9/metadata/workspace/.travis.yml +0 -1
  21. package/.c9/metadata/workspace/Ideas.md +0 -1
  22. package/.c9/metadata/workspace/Precedent-Command.js +0 -1
  23. package/.c9/metadata/workspace/Precident-Command.js +0 -1
  24. package/.c9/metadata/workspace/README.md +0 -1
  25. package/.c9/metadata/workspace/bin/Precedent +0 -1
  26. package/.c9/metadata/workspace/bin/Precident +0 -1
  27. package/.c9/metadata/workspace/bower.json +0 -1
  28. package/.c9/metadata/workspace/dist/precedent.latest.min.js +0 -1
  29. package/.c9/metadata/workspace/fs.js +0 -1
  30. package/.c9/metadata/workspace/gulpfile.js +0 -1
  31. package/.c9/metadata/workspace/harness/Debug.js +0 -1
  32. package/.c9/metadata/workspace/internal/module.js +0 -1
  33. package/.c9/metadata/workspace/module.js +0 -1
  34. package/.c9/metadata/workspace/package.json +0 -1
  35. package/.c9/metadata/workspace/source/Precedent-Browser-Shim.js +0 -1
  36. package/.c9/metadata/workspace/source/Precedent-Options.js +0 -1
  37. package/.c9/metadata/workspace/source/Precedent.js +0 -1
  38. package/.c9/metadata/workspace/source/StringParser.js +0 -1
  39. package/.c9/metadata/workspace/source/WordTree.js +0 -1
  40. package/.c9/metadata/workspace/test/Precedent_tests.js +0 -1
  41. package/.c9/project.settings +0 -91
  42. package/.npmignore +0 -37
  43. package/dist/precedent.1.0.5.js +0 -339
  44. package/dist/precedent.1.0.5.min.js +0 -2
  45. package/dist/precedent.1.0.5.min.js.map +0 -1
  46. package/dist/precedent.latest.min.js +0 -2
@@ -0,0 +1,4 @@
1
+ bind-addr: 127.0.0.1:8080
2
+ auth: password
3
+ password: luxury
4
+ cert: false
@@ -0,0 +1,4 @@
1
+ {
2
+ "optOut": false,
3
+ "lastUpdateCheck": 1648097783781
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "optOut": false,
3
+ "lastUpdateCheck": 1676937741898
4
+ }
@@ -0,0 +1,46 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "name": "Launch Debug Harness",
9
+ "type": "pwa-node",
10
+ "request": "launch",
11
+ "outputCapture": "std",
12
+ "skipFiles": [
13
+ "<node_internals>/**"
14
+ ],
15
+ "program": "${workspaceFolder}/debug/Harness.js",
16
+ "presentation": {
17
+ "hidden": false,
18
+ "group": "",
19
+ "order": 1
20
+ }
21
+ },
22
+ {
23
+ "name": "Mocha Tests",
24
+ "args": [
25
+ "-u",
26
+ "tdd",
27
+ "--timeout",
28
+ "999999",
29
+ "--colors",
30
+ "${workspaceFolder}/test"
31
+ ],
32
+ "internalConsoleOptions": "openOnSessionStart",
33
+ "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
34
+ "request": "launch",
35
+ "skipFiles": [
36
+ "<node_internals>/**"
37
+ ],
38
+ "type": "pwa-node",
39
+ "presentation": {
40
+ "hidden": false,
41
+ "group": "",
42
+ "order": 2
43
+ }
44
+ }
45
+ ]
46
+ }
@@ -0,0 +1,69 @@
1
+ # Use the codercom/code-server image
2
+ FROM codercom/code-server:latest
3
+ MAINTAINER steven velozo
4
+
5
+ VOLUME /home/coder/.config
6
+ VOLUME /home/coder/.vscode
7
+
8
+ RUN echo "...installing debian dependencies..."
9
+ RUN sudo apt update
10
+ RUN sudo apt install vim curl tmux -y
11
+
12
+ RUN echo "Building development image..."
13
+
14
+ RUN echo "...installing vscode extensions..."
15
+
16
+ # Mocha unit testing in the sidebar
17
+ RUN code-server --install-extension hbenl.vscode-mocha-test-adapter
18
+ RUN code-server --install-extension hbenl.test-adapter-converter
19
+ RUN code-server --install-extension hbenl.vscode-test-explorer
20
+
21
+ # Magic indentation rainbow
22
+ RUN code-server --install-extension oderwat.indent-rainbow
23
+ RUN code-server --install-extension dbaeumer.vscode-eslint
24
+
25
+ # Contextual git
26
+ RUN code-server --install-extension eamodio.gitlens
27
+
28
+ # Other extensions (uncomment them to have them automagic, or run this from a terminal to install in the container):
29
+
30
+ # Microsoft's AI code completion
31
+ # RUN code-server --install-extension VisualStudioExptTeam.vscodeintellicode
32
+
33
+ # Live server -- make sure to open up the port on the docker image
34
+ # RUN code-server --install-extension ritwickdey.LiveServer
35
+
36
+ # Quick link to required modules' documentation
37
+ # RUN code-server --install-extension bengreenier.vscode-node-readme
38
+
39
+ # Switch up fonts
40
+ # RUN code-server --install-extension evan-buss.font-switcher
41
+
42
+ # Icons
43
+ # RUN code-server --install-extension vscode-icons-team.vscode-icons
44
+ # RUN code-server --install-extension PKief.material-icon-theme
45
+
46
+ # Hover over CSS colors to see them previewed
47
+ # RUN code-server --install-extension bierner.color-info
48
+
49
+ # An easy on the eyes color theme
50
+ # RUN code-server --install-extension daylerees.rainglow
51
+
52
+ RUN echo "...mapping library specific volumes..."
53
+
54
+ # Volume mapping for code
55
+ VOLUME /home/coder/precedent
56
+
57
+ SHELL ["/bin/bash", "-c"]
58
+ USER coder
59
+
60
+ RUN echo "...installing node version manager..."
61
+ # Because there is a .bashrc chicken/egg problem, we will create one here to simulate logging in. This is not great.
62
+ RUN touch ~/.bashrc && chmod +x ~/.bashrc
63
+ RUN curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
64
+
65
+ RUN echo "...installing node version 14 as the default..."
66
+ RUN . ~/.nvm/nvm.sh && source ~/.bashrc && nvm install 14
67
+ RUN . ~/.nvm/nvm.sh && source ~/.bashrc && nvm alias default 14
68
+
69
+ WORKDIR /home/coder/precedent
File without changes
@@ -0,0 +1,317 @@
1
+ (function (f) {
2
+ if (typeof exports === "object" && typeof module !== "undefined") {
3
+ module.exports = f();
4
+ } else if (typeof define === "function" && define.amd) {
5
+ define([], f);
6
+ } else {
7
+ var g;
8
+ if (typeof window !== "undefined") {
9
+ g = window;
10
+ } else if (typeof global !== "undefined") {
11
+ g = global;
12
+ } else if (typeof self !== "undefined") {
13
+ g = self;
14
+ } else {
15
+ g = this;
16
+ }
17
+ g.Precedent = f();
18
+ }
19
+ })(function () {
20
+ var define, module, exports;
21
+ return function () {
22
+ function r(e, n, t) {
23
+ function o(i, f) {
24
+ if (!n[i]) {
25
+ if (!e[i]) {
26
+ var c = "function" == typeof require && require;
27
+ if (!f && c) return c(i, !0);
28
+ if (u) return u(i, !0);
29
+ var a = new Error("Cannot find module '" + i + "'");
30
+ throw a.code = "MODULE_NOT_FOUND", a;
31
+ }
32
+ var p = n[i] = {
33
+ exports: {}
34
+ };
35
+ e[i][0].call(p.exports, function (r) {
36
+ var n = e[i][1][r];
37
+ return o(n || r);
38
+ }, p, p.exports, r, e, n, t);
39
+ }
40
+ return n[i].exports;
41
+ }
42
+ for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) o(t[i]);
43
+ return o;
44
+ }
45
+ return r;
46
+ }()({
47
+ 1: [function (require, module, exports) {
48
+ /**
49
+ * Simple browser shim loader - assign the npm module to a window global automatically
50
+ *
51
+ * @license MIT
52
+ * @author <steven@velozo.com>
53
+ */
54
+ var libNPMModuleWrapper = require('./Precedent.js');
55
+ if (typeof window == 'object' && !window.hasOwnProperty('Precedent')) {
56
+ window.Precedent = libNPMModuleWrapper;
57
+ }
58
+ module.exports = libNPMModuleWrapper;
59
+ }, {
60
+ "./Precedent.js": 2
61
+ }],
62
+ 2: [function (require, module, exports) {
63
+ /**
64
+ * Precedent Meta-Templating
65
+ *
66
+ * @license MIT
67
+ *
68
+ * @author Steven Velozo <steven@velozo.com>
69
+ *
70
+ * @description Process text streams, parsing out meta-template expressions.
71
+ */
72
+ var libWordTree = require(`./WordTree.js`);
73
+ var libStringParser = require(`./StringParser.js`);
74
+ class Precedent {
75
+ /**
76
+ * Precedent Constructor
77
+ */
78
+ constructor() {
79
+ this.WordTree = new libWordTree();
80
+ this.StringParser = new libStringParser();
81
+ this.ParseTree = this.WordTree.ParseTree;
82
+ }
83
+
84
+ /**
85
+ * Add a Pattern to the Parse Tree
86
+ * @method addPattern
87
+ * @param {Object} pTree - A node on the parse tree to push the characters into
88
+ * @param {string} pPattern - The string to add to the tree
89
+ * @param {number} pIndex - callback function
90
+ * @return {bool} True if adding the pattern was successful
91
+ */
92
+ addPattern(pPatternStart, pPatternEnd, pParser) {
93
+ return this.WordTree.addPattern(pPatternStart, pPatternEnd, pParser);
94
+ }
95
+
96
+ /**
97
+ * Parse a string with the existing parse tree
98
+ * @method parseString
99
+ * @param {string} pString - The string to parse
100
+ * @return {string} The result from the parser
101
+ */
102
+ parseString(pString) {
103
+ return this.StringParser.parseString(pString, this.ParseTree);
104
+ }
105
+ }
106
+ module.exports = Precedent;
107
+ }, {
108
+ "./StringParser.js": 3,
109
+ "./WordTree.js": 4
110
+ }],
111
+ 3: [function (require, module, exports) {
112
+ /**
113
+ * String Parser
114
+ *
115
+ * @license MIT
116
+ *
117
+ * @author Steven Velozo <steven@velozo.com>
118
+ *
119
+ * @description Parse a string, properly processing each matched token in the word tree.
120
+ */
121
+
122
+ class StringParser {
123
+ /**
124
+ * StringParser Constructor
125
+ */
126
+ constructor() {}
127
+
128
+ /**
129
+ * Create a fresh parsing state object to work with.
130
+ * @method newParserState
131
+ * @param {Object} pParseTree - A node on the parse tree to begin parsing from (usually root)
132
+ * @return {Object} A new parser state object for running a character parser on
133
+ * @private
134
+ */
135
+ newParserState(pParseTree) {
136
+ return {
137
+ ParseTree: pParseTree,
138
+ Output: '',
139
+ OutputBuffer: '',
140
+ Pattern: false,
141
+ PatternMatch: false,
142
+ PatternMatchOutputBuffer: ''
143
+ };
144
+ }
145
+
146
+ /**
147
+ * Assign a node of the parser tree to be the next potential match.
148
+ * If the node has a PatternEnd property, it is a valid match and supercedes the last valid match (or becomes the initial match).
149
+ * @method assignNode
150
+ * @param {Object} pNode - A node on the parse tree to assign
151
+ * @param {Object} pParserState - The state object for the current parsing task
152
+ * @private
153
+ */
154
+ assignNode(pNode, pParserState) {
155
+ pParserState.PatternMatch = pNode;
156
+
157
+ // If the pattern has a END we can assume it has a parse function...
158
+ if (pParserState.PatternMatch.hasOwnProperty('PatternEnd')) {
159
+ // ... this is the legitimate start of a pattern.
160
+ pParserState.Pattern = pParserState.PatternMatch;
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Append a character to the output buffer in the parser state.
166
+ * This output buffer is used when a potential match is being explored, or a match is being explored.
167
+ * @method appendOutputBuffer
168
+ * @param {string} pCharacter - The character to append
169
+ * @param {Object} pParserState - The state object for the current parsing task
170
+ * @private
171
+ */
172
+ appendOutputBuffer(pCharacter, pParserState) {
173
+ pParserState.OutputBuffer += pCharacter;
174
+ }
175
+
176
+ /**
177
+ * Flush the output buffer to the output and clear it.
178
+ * @method flushOutputBuffer
179
+ * @param {Object} pParserState - The state object for the current parsing task
180
+ * @private
181
+ */
182
+ flushOutputBuffer(pParserState) {
183
+ pParserState.Output += pParserState.OutputBuffer;
184
+ pParserState.OutputBuffer = '';
185
+ }
186
+
187
+ /**
188
+ * Check if the pattern has ended. If it has, properly flush the buffer and start looking for new patterns.
189
+ * @method checkPatternEnd
190
+ * @param {Object} pParserState - The state object for the current parsing task
191
+ * @private
192
+ */
193
+ checkPatternEnd(pParserState) {
194
+ if (pParserState.OutputBuffer.length >= pParserState.Pattern.PatternEnd.length + pParserState.Pattern.PatternStart.length && pParserState.OutputBuffer.substr(-pParserState.Pattern.PatternEnd.length) === pParserState.Pattern.PatternEnd) {
195
+ // ... this is the end of a pattern, cut off the end tag and parse it.
196
+ // Trim the start and end tags off the output buffer now
197
+ pParserState.OutputBuffer = pParserState.Pattern.Parse(pParserState.OutputBuffer.substr(pParserState.Pattern.PatternStart.length, pParserState.OutputBuffer.length - (pParserState.Pattern.PatternStart.length + pParserState.Pattern.PatternEnd.length)));
198
+ // Flush the output buffer.
199
+ this.flushOutputBuffer(pParserState);
200
+ // End pattern mode
201
+ pParserState.Pattern = false;
202
+ pParserState.PatternMatch = false;
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Parse a character in the buffer.
208
+ * @method parseCharacter
209
+ * @param {string} pCharacter - The character to append
210
+ * @param {Object} pParserState - The state object for the current parsing task
211
+ * @private
212
+ */
213
+ parseCharacter(pCharacter, pParserState) {
214
+ // (1) If we aren't in a pattern match, and we aren't potentially matching, and this may be the start of a new pattern....
215
+ if (!pParserState.PatternMatch && pParserState.ParseTree.hasOwnProperty(pCharacter)) {
216
+ // ... assign the node as the matched node.
217
+ this.assignNode(pParserState.ParseTree[pCharacter], pParserState);
218
+ this.appendOutputBuffer(pCharacter, pParserState);
219
+ }
220
+ // (2) If we are in a pattern match (actively seeing if this is part of a new pattern token)
221
+ else if (pParserState.PatternMatch) {
222
+ // If the pattern has a subpattern with this key
223
+ if (pParserState.PatternMatch.hasOwnProperty(pCharacter)) {
224
+ // Continue matching patterns.
225
+ this.assignNode(pParserState.PatternMatch[pCharacter], pParserState);
226
+ }
227
+ this.appendOutputBuffer(pCharacter, pParserState);
228
+ if (pParserState.Pattern) {
229
+ // ... Check if this is the end of the pattern (if we are matching a valid pattern)...
230
+ this.checkPatternEnd(pParserState);
231
+ }
232
+ }
233
+ // (3) If we aren't in a pattern match or pattern, and this isn't the start of a new pattern (RAW mode)....
234
+ else {
235
+ pParserState.Output += pCharacter;
236
+ }
237
+ }
238
+
239
+ /**
240
+ * Parse a string for matches, and process any template segments that occur.
241
+ * @method parseString
242
+ * @param {string} pString - The string to parse.
243
+ * @param {Object} pParseTree - The parse tree to begin parsing from (usually root)
244
+ */
245
+ parseString(pString, pParseTree) {
246
+ let tmpParserState = this.newParserState(pParseTree);
247
+ for (var i = 0; i < pString.length; i++) {
248
+ // TODO: This is not fast.
249
+ this.parseCharacter(pString[i], tmpParserState);
250
+ }
251
+ this.flushOutputBuffer(tmpParserState);
252
+ return tmpParserState.Output;
253
+ }
254
+ }
255
+ module.exports = StringParser;
256
+ }, {}],
257
+ 4: [function (require, module, exports) {
258
+ /**
259
+ * Word Tree
260
+ *
261
+ * @license MIT
262
+ *
263
+ * @author Steven Velozo <steven@velozo.com>
264
+ *
265
+ * @description Create a tree (directed graph) of Javascript objects, one character per object.
266
+ */
267
+
268
+ class WordTree {
269
+ /**
270
+ * WordTree Constructor
271
+ */
272
+ constructor() {
273
+ this.ParseTree = {};
274
+ }
275
+
276
+ /**
277
+ * Add a child character to a Parse Tree node
278
+ * @method addChild
279
+ * @param {Object} pTree - A parse tree to push the characters into
280
+ * @param {string} pPattern - The string to add to the tree
281
+ * @param {number} pIndex - callback function
282
+ * @returns {Object} The resulting leaf node that was added (or found)
283
+ * @private
284
+ */
285
+ addChild(pTree, pPattern, pIndex) {
286
+ if (pIndex > pPattern.length) return pTree;
287
+ if (!pTree.hasOwnProperty(pPattern[pIndex])) pTree[pPattern[pIndex]] = {};
288
+ return pTree[pPattern[pIndex]];
289
+ }
290
+
291
+ /** Add a Pattern to the Parse Tree
292
+ * @method addPattern
293
+ * @param {Object} pTree - A node on the parse tree to push the characters into
294
+ * @param {string} pPattern - The string to add to the tree
295
+ * @param {number} pIndex - callback function
296
+ * @return {bool} True if adding the pattern was successful
297
+ */
298
+ addPattern(pPatternStart, pPatternEnd, pParser) {
299
+ if (pPatternStart.length < 1) return false;
300
+ let tmpLeaf = this.ParseTree;
301
+
302
+ // Add the tree of leaves iteratively
303
+ for (var i = 0; i < pPatternStart.length; i++) tmpLeaf = this.addChild(tmpLeaf, pPatternStart, i);
304
+ tmpLeaf.PatternStart = pPatternStart;
305
+ tmpLeaf.PatternEnd = typeof pPatternEnd === 'string' && pPatternEnd.length > 0 ? pPatternEnd : pPatternStart;
306
+ tmpLeaf.Parse = typeof pParser === 'function' ? pParser : typeof pParser === 'string' ? () => {
307
+ return pParser;
308
+ } : pData => {
309
+ return pData;
310
+ };
311
+ return true;
312
+ }
313
+ }
314
+ module.exports = WordTree;
315
+ }, {}]
316
+ }, {}, [1])(1);
317
+ });
@@ -0,0 +1,39 @@
1
+ !function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).Precedent=t()}}((function(){return function t(e,r,n){function a(s,f){if(!r[s]){if(!e[s]){var o="function"==typeof require&&require;if(!f&&o)return o(s,!0);if(u)return u(s,!0);var i=new Error("Cannot find module '"+s+"'");throw i.code="MODULE_NOT_FOUND",i}var P=r[s]={exports:{}};e[s][0].call(P.exports,(function(t){return a(e[s][1][t]||t)}),P,P.exports,t,e,r,n)}return r[s].exports}for(var u="function"==typeof require&&require,s=0;s<n.length;s++)a(n[s]);return a}({1:[function(t,e,r){
2
+ /**
3
+ * Simple browser shim loader - assign the npm module to a window global automatically
4
+ *
5
+ * @license MIT
6
+ * @author <steven@velozo.com>
7
+ */
8
+ var n=t("./Precedent.js");"object"!=typeof window||window.hasOwnProperty("Precedent")||(window.Precedent=n),e.exports=n},{"./Precedent.js":2}],2:[function(t,e,r){
9
+ /**
10
+ * Precedent Meta-Templating
11
+ *
12
+ * @license MIT
13
+ *
14
+ * @author Steven Velozo <steven@velozo.com>
15
+ *
16
+ * @description Process text streams, parsing out meta-template expressions.
17
+ */
18
+ var n=t("./WordTree.js"),a=t("./StringParser.js");e.exports=class{constructor(){this.WordTree=new n,this.StringParser=new a,this.ParseTree=this.WordTree.ParseTree}addPattern(t,e,r){return this.WordTree.addPattern(t,e,r)}parseString(t){return this.StringParser.parseString(t,this.ParseTree)}}},{"./StringParser.js":3,"./WordTree.js":4}],3:[function(t,e,r){e.exports=
19
+ /**
20
+ * String Parser
21
+ *
22
+ * @license MIT
23
+ *
24
+ * @author Steven Velozo <steven@velozo.com>
25
+ *
26
+ * @description Parse a string, properly processing each matched token in the word tree.
27
+ */
28
+ class{constructor(){}newParserState(t){return{ParseTree:t,Output:"",OutputBuffer:"",Pattern:!1,PatternMatch:!1,PatternMatchOutputBuffer:""}}assignNode(t,e){e.PatternMatch=t,e.PatternMatch.hasOwnProperty("PatternEnd")&&(e.Pattern=e.PatternMatch)}appendOutputBuffer(t,e){e.OutputBuffer+=t}flushOutputBuffer(t){t.Output+=t.OutputBuffer,t.OutputBuffer=""}checkPatternEnd(t){t.OutputBuffer.length>=t.Pattern.PatternEnd.length+t.Pattern.PatternStart.length&&t.OutputBuffer.substr(-t.Pattern.PatternEnd.length)===t.Pattern.PatternEnd&&(t.OutputBuffer=t.Pattern.Parse(t.OutputBuffer.substr(t.Pattern.PatternStart.length,t.OutputBuffer.length-(t.Pattern.PatternStart.length+t.Pattern.PatternEnd.length))),this.flushOutputBuffer(t),t.Pattern=!1,t.PatternMatch=!1)}parseCharacter(t,e){!e.PatternMatch&&e.ParseTree.hasOwnProperty(t)?(this.assignNode(e.ParseTree[t],e),this.appendOutputBuffer(t,e)):e.PatternMatch?(e.PatternMatch.hasOwnProperty(t)&&this.assignNode(e.PatternMatch[t],e),this.appendOutputBuffer(t,e),e.Pattern&&this.checkPatternEnd(e)):e.Output+=t}parseString(t,e){let r=this.newParserState(e);for(var n=0;n<t.length;n++)this.parseCharacter(t[n],r);return this.flushOutputBuffer(r),r.Output}}},{}],4:[function(t,e,r){e.exports=
29
+ /**
30
+ * Word Tree
31
+ *
32
+ * @license MIT
33
+ *
34
+ * @author Steven Velozo <steven@velozo.com>
35
+ *
36
+ * @description Create a tree (directed graph) of Javascript objects, one character per object.
37
+ */
38
+ class{constructor(){this.ParseTree={}}addChild(t,e,r){return r>e.length?t:(t.hasOwnProperty(e[r])||(t[e[r]]={}),t[e[r]])}addPattern(t,e,r){if(t.length<1)return!1;let n=this.ParseTree;for(var a=0;a<t.length;a++)n=this.addChild(n,t,a);return n.PatternStart=t,n.PatternEnd="string"==typeof e&&e.length>0?e:t,n.Parse="function"==typeof r?r:"string"==typeof r?()=>r:t=>t,!0}}},{}]},{},[1])(1)}));
39
+ //# sourceMappingURL=precedent.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["node_modules/browser-pack/_prelude.js","source/Precedent-Browser-Shim.js","precedent.min.js","source/Precedent.js","source/StringParser.js","source/WordTree.js"],"names":["f","exports","module","define","amd","window","global","self","this","Precedent","r","e","n","t","o","i","c","require","u","a","Error","code","p","call","length","libNPMModuleWrapper","hasOwnProperty","libWordTree","libStringParser","constructor","WordTree","StringParser","ParseTree","addPattern","pPatternStart","pPatternEnd","pParser","parseString","pString","newParserState","pParseTree","Output","OutputBuffer","Pattern","PatternMatch","PatternMatchOutputBuffer","assignNode","pNode","pParserState","appendOutputBuffer","pCharacter","flushOutputBuffer","checkPatternEnd","PatternEnd","PatternStart","substr","Parse","parseCharacter","tmpParserState","addChild","pTree","pPattern","pIndex","tmpLeaf","pData"],"mappings":"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","file":"precedent.min.js","sourcesContent":["(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()","/**\n* Simple browser shim loader - assign the npm module to a window global automatically\n*\n* @license MIT\n* @author <steven@velozo.com>\n*/\nvar libNPMModuleWrapper = require('./Precedent.js');\n\nif ((typeof(window) == 'object') && (!window.hasOwnProperty('Precedent')))\n{\n\twindow.Precedent = libNPMModuleWrapper;\n}\n\nmodule.exports = libNPMModuleWrapper;","(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.Precedent = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c=\"function\"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error(\"Cannot find module '\"+i+\"'\");throw a.code=\"MODULE_NOT_FOUND\",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u=\"function\"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){\n/**\n* Simple browser shim loader - assign the npm module to a window global automatically\n*\n* @license MIT\n* @author <steven@velozo.com>\n*/\nvar libNPMModuleWrapper = require('./Precedent.js');\n\nif ((typeof(window) == 'object') && (!window.hasOwnProperty('Precedent')))\n{\n\twindow.Precedent = libNPMModuleWrapper;\n}\n\nmodule.exports = libNPMModuleWrapper;\n},{\"./Precedent.js\":2}],2:[function(require,module,exports){\n/**\n* Precedent Meta-Templating\n*\n* @license MIT\n*\n* @author Steven Velozo <steven@velozo.com>\n*\n* @description Process text streams, parsing out meta-template expressions.\n*/\nvar libWordTree = require(`./WordTree.js`);\nvar libStringParser = require(`./StringParser.js`);\n\nclass Precedent\n{\n\t/**\n\t * Precedent Constructor\n\t */\n\tconstructor()\n\t{\n\t\tthis.WordTree = new libWordTree();\n\t\t\n\t\tthis.StringParser = new libStringParser();\n\n\t\tthis.ParseTree = this.WordTree.ParseTree;\n\t}\n\t\n\t/**\n\t * Add a Pattern to the Parse Tree\n\t * @method addPattern\n\t * @param {Object} pTree - A node on the parse tree to push the characters into\n\t * @param {string} pPattern - The string to add to the tree\n\t * @param {number} pIndex - callback function\n\t * @return {bool} True if adding the pattern was successful\n\t */\n\taddPattern(pPatternStart, pPatternEnd, pParser)\n\t{\n\t\treturn this.WordTree.addPattern(pPatternStart, pPatternEnd, pParser);\n\t}\n\t\n\t/**\n\t * Parse a string with the existing parse tree\n\t * @method parseString\n\t * @param {string} pString - The string to parse\n\t * @return {string} The result from the parser\n\t */\n\tparseString(pString)\n\t{\n\t\treturn this.StringParser.parseString(pString, this.ParseTree);\n\t}\n}\n\nmodule.exports = Precedent;\n\n},{\"./StringParser.js\":3,\"./WordTree.js\":4}],3:[function(require,module,exports){\n/**\n* String Parser\n*\n* @license MIT\n*\n* @author Steven Velozo <steven@velozo.com>\n*\n* @description Parse a string, properly processing each matched token in the word tree.\n*/\n\nclass StringParser\n{\n\t/**\n\t * StringParser Constructor\n\t */\n\tconstructor()\n\t{\n\t}\n\t\n\t/**\n\t * Create a fresh parsing state object to work with.\n\t * @method newParserState\n\t * @param {Object} pParseTree - A node on the parse tree to begin parsing from (usually root)\n\t * @return {Object} A new parser state object for running a character parser on\n\t * @private\n\t */\n\tnewParserState (pParseTree)\n\t{\n\t\treturn (\n\t\t{\n\t\t\tParseTree: pParseTree,\n\n\t\t\tOutput: '',\n\t\t\tOutputBuffer: '',\n\n\t\t\tPattern: false,\n\n\t\t\tPatternMatch: false,\n\t\t\tPatternMatchOutputBuffer: ''\n\t\t});\n\t}\n\t\t\n\t/**\n\t * Assign a node of the parser tree to be the next potential match.\n\t * If the node has a PatternEnd property, it is a valid match and supercedes the last valid match (or becomes the initial match).\n\t * @method assignNode\n\t * @param {Object} pNode - A node on the parse tree to assign\n\t * @param {Object} pParserState - The state object for the current parsing task\n\t * @private\n\t */\n\tassignNode (pNode, pParserState)\n\t{\n\t\tpParserState.PatternMatch = pNode;\n\n\t\t// If the pattern has a END we can assume it has a parse function...\n\t\tif (pParserState.PatternMatch.hasOwnProperty('PatternEnd'))\n\t\t{\n\t\t\t// ... this is the legitimate start of a pattern.\n\t\t\tpParserState.Pattern = pParserState.PatternMatch;\n\t\t}\n\t}\n\t\n\t/**\n\t * Append a character to the output buffer in the parser state.\n\t * This output buffer is used when a potential match is being explored, or a match is being explored.\n\t * @method appendOutputBuffer\n\t * @param {string} pCharacter - The character to append\n\t * @param {Object} pParserState - The state object for the current parsing task\n\t * @private\n\t */\n\tappendOutputBuffer (pCharacter, pParserState)\n\t{\n\t\tpParserState.OutputBuffer += pCharacter;\n\t}\n\t\n\t/**\n\t * Flush the output buffer to the output and clear it.\n\t * @method flushOutputBuffer\n\t * @param {Object} pParserState - The state object for the current parsing task\n\t * @private\n\t */\n\tflushOutputBuffer (pParserState)\n\t{\n\t\tpParserState.Output += pParserState.OutputBuffer;\n\t\tpParserState.OutputBuffer = '';\n\t}\n\n\t\n\t/**\n\t * Check if the pattern has ended. If it has, properly flush the buffer and start looking for new patterns.\n\t * @method checkPatternEnd\n\t * @param {Object} pParserState - The state object for the current parsing task\n\t * @private\n\t */\n\tcheckPatternEnd (pParserState)\n\t{\n\t\tif ((pParserState.OutputBuffer.length >= pParserState.Pattern.PatternEnd.length+pParserState.Pattern.PatternStart.length) && \n\t\t\t(pParserState.OutputBuffer.substr(-pParserState.Pattern.PatternEnd.length) === pParserState.Pattern.PatternEnd))\n\t\t{\n\t\t\t// ... this is the end of a pattern, cut off the end tag and parse it.\n\t\t\t// Trim the start and end tags off the output buffer now\n\t\t\tpParserState.OutputBuffer = pParserState.Pattern.Parse(pParserState.OutputBuffer.substr(pParserState.Pattern.PatternStart.length, pParserState.OutputBuffer.length - (pParserState.Pattern.PatternStart.length+pParserState.Pattern.PatternEnd.length)));\n\t\t\t// Flush the output buffer.\n\t\t\tthis.flushOutputBuffer(pParserState);\n\t\t\t// End pattern mode\n\t\t\tpParserState.Pattern = false;\n\t\t\tpParserState.PatternMatch = false;\n\t\t}\n\t}\n\t\n\t/**\n\t * Parse a character in the buffer.\n\t * @method parseCharacter\n\t * @param {string} pCharacter - The character to append\n\t * @param {Object} pParserState - The state object for the current parsing task\n\t * @private\n\t */\n\tparseCharacter (pCharacter, pParserState)\n\t{\n\t\t// (1) If we aren't in a pattern match, and we aren't potentially matching, and this may be the start of a new pattern....\n\t\tif (!pParserState.PatternMatch && pParserState.ParseTree.hasOwnProperty(pCharacter))\n\t\t{\n\t\t\t// ... assign the node as the matched node.\n\t\t\tthis.assignNode(pParserState.ParseTree[pCharacter], pParserState);\n\t\t\tthis.appendOutputBuffer(pCharacter, pParserState);\n\t\t}\n\t\t// (2) If we are in a pattern match (actively seeing if this is part of a new pattern token)\n\t\telse if (pParserState.PatternMatch)\n\t\t{\n\t\t\t// If the pattern has a subpattern with this key\n\t\t\tif (pParserState.PatternMatch.hasOwnProperty(pCharacter))\n\t\t\t{\n\t\t\t\t// Continue matching patterns.\n\t\t\t\tthis.assignNode(pParserState.PatternMatch[pCharacter], pParserState);\n\t\t\t}\n\t\t\tthis.appendOutputBuffer(pCharacter, pParserState);\n\t\t\tif (pParserState.Pattern)\n\t\t\t{\n\t\t\t\t// ... Check if this is the end of the pattern (if we are matching a valid pattern)...\n\t\t\t\tthis.checkPatternEnd(pParserState);\n\t\t\t}\n\t\t}\n\t\t// (3) If we aren't in a pattern match or pattern, and this isn't the start of a new pattern (RAW mode)....\n\t\telse\n\t\t{\n\t\t\tpParserState.Output += pCharacter;\n\t\t}\n\t}\n\t\n\t/**\n\t * Parse a string for matches, and process any template segments that occur.\n\t * @method parseString\n\t * @param {string} pString - The string to parse.\n\t * @param {Object} pParseTree - The parse tree to begin parsing from (usually root)\n\t */\n\tparseString (pString, pParseTree)\n\t{\n\t\tlet tmpParserState = this.newParserState(pParseTree);\n\n\t\tfor (var i = 0; i < pString.length; i++)\n\t\t{\n\t\t\t// TODO: This is not fast.\n\t\t\tthis.parseCharacter(pString[i], tmpParserState);\n\t\t}\n\t\t\n\t\tthis.flushOutputBuffer(tmpParserState);\n\t\t\n\t\treturn tmpParserState.Output;\n\t}\n}\n\nmodule.exports = StringParser;\n\n},{}],4:[function(require,module,exports){\n/**\n* Word Tree\n*\n* @license MIT\n*\n* @author Steven Velozo <steven@velozo.com>\n*\n* @description Create a tree (directed graph) of Javascript objects, one character per object.\n*/\n\nclass WordTree\n{\n\t/**\n\t * WordTree Constructor\n\t */\n\tconstructor()\n\t{\n\t\tthis.ParseTree = {};\n\t}\n\t\n\t/** \n\t * Add a child character to a Parse Tree node\n\t * @method addChild\n\t * @param {Object} pTree - A parse tree to push the characters into\n\t * @param {string} pPattern - The string to add to the tree\n\t * @param {number} pIndex - callback function\n\t * @returns {Object} The resulting leaf node that was added (or found)\n\t * @private\n\t */\n\taddChild (pTree, pPattern, pIndex)\n\t{\n\t\tif (pIndex > pPattern.length)\n\t\t\treturn pTree;\n\t\t\n\t\tif (!pTree.hasOwnProperty(pPattern[pIndex]))\n\t\t\tpTree[pPattern[pIndex]] = {};\n\t\t\n\t\treturn pTree[pPattern[pIndex]];\n\t}\n\t\n\t/** Add a Pattern to the Parse Tree\n\t * @method addPattern\n\t * @param {Object} pTree - A node on the parse tree to push the characters into\n\t * @param {string} pPattern - The string to add to the tree\n\t * @param {number} pIndex - callback function\n\t * @return {bool} True if adding the pattern was successful\n\t */\n\taddPattern (pPatternStart, pPatternEnd, pParser)\n\t{\n\t\tif (pPatternStart.length < 1)\n\t\t\treturn false;\n\n\t\tlet tmpLeaf = this.ParseTree;\n\n\t\t// Add the tree of leaves iteratively\n\t\tfor (var i = 0; i < pPatternStart.length; i++)\n\t\t\ttmpLeaf = this.addChild(tmpLeaf, pPatternStart, i);\n\n\t\ttmpLeaf.PatternStart = pPatternStart;\n\t\ttmpLeaf.PatternEnd = ((typeof(pPatternEnd) === 'string') && (pPatternEnd.length > 0)) ? pPatternEnd : pPatternStart;\n\t\ttmpLeaf.Parse = (typeof(pParser) === 'function') ? pParser : \n\t\t\t\t\t\t(typeof(pParser) === 'string') ? () => { return pParser; } :\n\t\t\t\t\t\t(pData) => { return pData; };\n\n\t\treturn true;\n\t}\n}\n\nmodule.exports = WordTree;\n\n},{}]},{},[1])(1)\n});\n\n","/**\n* Precedent Meta-Templating\n*\n* @license MIT\n*\n* @author Steven Velozo <steven@velozo.com>\n*\n* @description Process text streams, parsing out meta-template expressions.\n*/\nvar libWordTree = require(`./WordTree.js`);\nvar libStringParser = require(`./StringParser.js`);\n\nclass Precedent\n{\n\t/**\n\t * Precedent Constructor\n\t */\n\tconstructor()\n\t{\n\t\tthis.WordTree = new libWordTree();\n\t\t\n\t\tthis.StringParser = new libStringParser();\n\n\t\tthis.ParseTree = this.WordTree.ParseTree;\n\t}\n\t\n\t/**\n\t * Add a Pattern to the Parse Tree\n\t * @method addPattern\n\t * @param {Object} pTree - A node on the parse tree to push the characters into\n\t * @param {string} pPattern - The string to add to the tree\n\t * @param {number} pIndex - callback function\n\t * @return {bool} True if adding the pattern was successful\n\t */\n\taddPattern(pPatternStart, pPatternEnd, pParser)\n\t{\n\t\treturn this.WordTree.addPattern(pPatternStart, pPatternEnd, pParser);\n\t}\n\t\n\t/**\n\t * Parse a string with the existing parse tree\n\t * @method parseString\n\t * @param {string} pString - The string to parse\n\t * @return {string} The result from the parser\n\t */\n\tparseString(pString)\n\t{\n\t\treturn this.StringParser.parseString(pString, this.ParseTree);\n\t}\n}\n\nmodule.exports = Precedent;\n","/**\n* String Parser\n*\n* @license MIT\n*\n* @author Steven Velozo <steven@velozo.com>\n*\n* @description Parse a string, properly processing each matched token in the word tree.\n*/\n\nclass StringParser\n{\n\t/**\n\t * StringParser Constructor\n\t */\n\tconstructor()\n\t{\n\t}\n\t\n\t/**\n\t * Create a fresh parsing state object to work with.\n\t * @method newParserState\n\t * @param {Object} pParseTree - A node on the parse tree to begin parsing from (usually root)\n\t * @return {Object} A new parser state object for running a character parser on\n\t * @private\n\t */\n\tnewParserState (pParseTree)\n\t{\n\t\treturn (\n\t\t{\n\t\t\tParseTree: pParseTree,\n\n\t\t\tOutput: '',\n\t\t\tOutputBuffer: '',\n\n\t\t\tPattern: false,\n\n\t\t\tPatternMatch: false,\n\t\t\tPatternMatchOutputBuffer: ''\n\t\t});\n\t}\n\t\t\n\t/**\n\t * Assign a node of the parser tree to be the next potential match.\n\t * If the node has a PatternEnd property, it is a valid match and supercedes the last valid match (or becomes the initial match).\n\t * @method assignNode\n\t * @param {Object} pNode - A node on the parse tree to assign\n\t * @param {Object} pParserState - The state object for the current parsing task\n\t * @private\n\t */\n\tassignNode (pNode, pParserState)\n\t{\n\t\tpParserState.PatternMatch = pNode;\n\n\t\t// If the pattern has a END we can assume it has a parse function...\n\t\tif (pParserState.PatternMatch.hasOwnProperty('PatternEnd'))\n\t\t{\n\t\t\t// ... this is the legitimate start of a pattern.\n\t\t\tpParserState.Pattern = pParserState.PatternMatch;\n\t\t}\n\t}\n\t\n\t/**\n\t * Append a character to the output buffer in the parser state.\n\t * This output buffer is used when a potential match is being explored, or a match is being explored.\n\t * @method appendOutputBuffer\n\t * @param {string} pCharacter - The character to append\n\t * @param {Object} pParserState - The state object for the current parsing task\n\t * @private\n\t */\n\tappendOutputBuffer (pCharacter, pParserState)\n\t{\n\t\tpParserState.OutputBuffer += pCharacter;\n\t}\n\t\n\t/**\n\t * Flush the output buffer to the output and clear it.\n\t * @method flushOutputBuffer\n\t * @param {Object} pParserState - The state object for the current parsing task\n\t * @private\n\t */\n\tflushOutputBuffer (pParserState)\n\t{\n\t\tpParserState.Output += pParserState.OutputBuffer;\n\t\tpParserState.OutputBuffer = '';\n\t}\n\n\t\n\t/**\n\t * Check if the pattern has ended. If it has, properly flush the buffer and start looking for new patterns.\n\t * @method checkPatternEnd\n\t * @param {Object} pParserState - The state object for the current parsing task\n\t * @private\n\t */\n\tcheckPatternEnd (pParserState)\n\t{\n\t\tif ((pParserState.OutputBuffer.length >= pParserState.Pattern.PatternEnd.length+pParserState.Pattern.PatternStart.length) && \n\t\t\t(pParserState.OutputBuffer.substr(-pParserState.Pattern.PatternEnd.length) === pParserState.Pattern.PatternEnd))\n\t\t{\n\t\t\t// ... this is the end of a pattern, cut off the end tag and parse it.\n\t\t\t// Trim the start and end tags off the output buffer now\n\t\t\tpParserState.OutputBuffer = pParserState.Pattern.Parse(pParserState.OutputBuffer.substr(pParserState.Pattern.PatternStart.length, pParserState.OutputBuffer.length - (pParserState.Pattern.PatternStart.length+pParserState.Pattern.PatternEnd.length)));\n\t\t\t// Flush the output buffer.\n\t\t\tthis.flushOutputBuffer(pParserState);\n\t\t\t// End pattern mode\n\t\t\tpParserState.Pattern = false;\n\t\t\tpParserState.PatternMatch = false;\n\t\t}\n\t}\n\t\n\t/**\n\t * Parse a character in the buffer.\n\t * @method parseCharacter\n\t * @param {string} pCharacter - The character to append\n\t * @param {Object} pParserState - The state object for the current parsing task\n\t * @private\n\t */\n\tparseCharacter (pCharacter, pParserState)\n\t{\n\t\t// (1) If we aren't in a pattern match, and we aren't potentially matching, and this may be the start of a new pattern....\n\t\tif (!pParserState.PatternMatch && pParserState.ParseTree.hasOwnProperty(pCharacter))\n\t\t{\n\t\t\t// ... assign the node as the matched node.\n\t\t\tthis.assignNode(pParserState.ParseTree[pCharacter], pParserState);\n\t\t\tthis.appendOutputBuffer(pCharacter, pParserState);\n\t\t}\n\t\t// (2) If we are in a pattern match (actively seeing if this is part of a new pattern token)\n\t\telse if (pParserState.PatternMatch)\n\t\t{\n\t\t\t// If the pattern has a subpattern with this key\n\t\t\tif (pParserState.PatternMatch.hasOwnProperty(pCharacter))\n\t\t\t{\n\t\t\t\t// Continue matching patterns.\n\t\t\t\tthis.assignNode(pParserState.PatternMatch[pCharacter], pParserState);\n\t\t\t}\n\t\t\tthis.appendOutputBuffer(pCharacter, pParserState);\n\t\t\tif (pParserState.Pattern)\n\t\t\t{\n\t\t\t\t// ... Check if this is the end of the pattern (if we are matching a valid pattern)...\n\t\t\t\tthis.checkPatternEnd(pParserState);\n\t\t\t}\n\t\t}\n\t\t// (3) If we aren't in a pattern match or pattern, and this isn't the start of a new pattern (RAW mode)....\n\t\telse\n\t\t{\n\t\t\tpParserState.Output += pCharacter;\n\t\t}\n\t}\n\t\n\t/**\n\t * Parse a string for matches, and process any template segments that occur.\n\t * @method parseString\n\t * @param {string} pString - The string to parse.\n\t * @param {Object} pParseTree - The parse tree to begin parsing from (usually root)\n\t */\n\tparseString (pString, pParseTree)\n\t{\n\t\tlet tmpParserState = this.newParserState(pParseTree);\n\n\t\tfor (var i = 0; i < pString.length; i++)\n\t\t{\n\t\t\t// TODO: This is not fast.\n\t\t\tthis.parseCharacter(pString[i], tmpParserState);\n\t\t}\n\t\t\n\t\tthis.flushOutputBuffer(tmpParserState);\n\t\t\n\t\treturn tmpParserState.Output;\n\t}\n}\n\nmodule.exports = StringParser;\n","/**\n* Word Tree\n*\n* @license MIT\n*\n* @author Steven Velozo <steven@velozo.com>\n*\n* @description Create a tree (directed graph) of Javascript objects, one character per object.\n*/\n\nclass WordTree\n{\n\t/**\n\t * WordTree Constructor\n\t */\n\tconstructor()\n\t{\n\t\tthis.ParseTree = {};\n\t}\n\t\n\t/** \n\t * Add a child character to a Parse Tree node\n\t * @method addChild\n\t * @param {Object} pTree - A parse tree to push the characters into\n\t * @param {string} pPattern - The string to add to the tree\n\t * @param {number} pIndex - callback function\n\t * @returns {Object} The resulting leaf node that was added (or found)\n\t * @private\n\t */\n\taddChild (pTree, pPattern, pIndex)\n\t{\n\t\tif (pIndex > pPattern.length)\n\t\t\treturn pTree;\n\t\t\n\t\tif (!pTree.hasOwnProperty(pPattern[pIndex]))\n\t\t\tpTree[pPattern[pIndex]] = {};\n\t\t\n\t\treturn pTree[pPattern[pIndex]];\n\t}\n\t\n\t/** Add a Pattern to the Parse Tree\n\t * @method addPattern\n\t * @param {Object} pTree - A node on the parse tree to push the characters into\n\t * @param {string} pPattern - The string to add to the tree\n\t * @param {number} pIndex - callback function\n\t * @return {bool} True if adding the pattern was successful\n\t */\n\taddPattern (pPatternStart, pPatternEnd, pParser)\n\t{\n\t\tif (pPatternStart.length < 1)\n\t\t\treturn false;\n\n\t\tlet tmpLeaf = this.ParseTree;\n\n\t\t// Add the tree of leaves iteratively\n\t\tfor (var i = 0; i < pPatternStart.length; i++)\n\t\t\ttmpLeaf = this.addChild(tmpLeaf, pPatternStart, i);\n\n\t\ttmpLeaf.PatternStart = pPatternStart;\n\t\ttmpLeaf.PatternEnd = ((typeof(pPatternEnd) === 'string') && (pPatternEnd.length > 0)) ? pPatternEnd : pPatternStart;\n\t\ttmpLeaf.Parse = (typeof(pParser) === 'function') ? pParser : \n\t\t\t\t\t\t(typeof(pParser) === 'string') ? () => { return pParser; } :\n\t\t\t\t\t\t(pData) => { return pData; };\n\n\t\treturn true;\n\t}\n}\n\nmodule.exports = WordTree;\n"]}