fable 3.0.47 → 3.0.49

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.
@@ -5,7 +5,7 @@
5
5
 
6
6
  "LibraryOutputFolder": "./dist/",
7
7
 
8
- "LibraryUniminifiedFileName": "fable.compatible.js",
8
+ "LibraryUniminifiedFileName": "fable.js",
9
9
 
10
- "LibraryMinifiedFileName": "fable.compatible.min.js"
10
+ "LibraryMinifiedFileName": "fable.min.js"
11
11
  }
package/gulpfile.js CHANGED
@@ -131,7 +131,7 @@ libGulp.task('minified',
131
131
  .pipe(libVinylBuffer())
132
132
  .pipe(libSourcemaps.init({loadMaps: true}))
133
133
  // Add transformation tasks to the pipeline here.
134
- .pipe(libBabel())
134
+ .pipe(libBabel({"presets": ["@babel/preset-env"]}))
135
135
  .pipe(libTerser())
136
136
  .on('error', libGulpUtil.log)
137
137
  .pipe(libSourcemaps.write('./'))
@@ -152,7 +152,7 @@ libGulp.task('debug',
152
152
  return tmpBrowserify.bundle()
153
153
  .pipe(libVinylSourceStream(_CONFIG.LibraryUniminifiedFileName))
154
154
  .pipe(libVinylBuffer())
155
- .pipe(libBabel())
155
+ .pipe(libBabel({"presets": ["@babel/preset-env"]}))
156
156
  .on('error', libGulpUtil.log)
157
157
  .pipe(libGulp.dest(_CONFIG.LibraryOutputFolder));
158
158
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fable",
3
- "version": "3.0.47",
3
+ "version": "3.0.49",
4
4
  "description": "An entity behavior management and API bundling library.",
5
5
  "main": "source/Fable.js",
6
6
  "scripts": {
@@ -54,6 +54,25 @@ class FableService extends libFableServiceBase.CoreServiceProviderBase
54
54
  this.instantiateServiceProvider(pServiceType, {}, `${pServiceType}-Default`);
55
55
  }
56
56
 
57
+ // Some servicds expect to be overloaded / customized class.
58
+ instantiateServiceProviderFromPrototype(pServiceType, pOptions, pCustomServiceHash, pServicePrototype)
59
+ {
60
+ // Instantiate the service
61
+ let tmpService = new pServicePrototype(this.fable, pOptions, pCustomServiceHash);
62
+
63
+ // Add the service to the service map
64
+ this.services[pServiceType][tmpService.Hash] = tmpService;
65
+
66
+ // If this is the first service of this type, make it the default
67
+ if (!this.defaultServices.hasOwnProperty(pServiceType))
68
+ {
69
+ this.setDefaultServiceInstantiation(pServiceType, tmpService.Hash)
70
+ }
71
+
72
+ return tmpService;
73
+ }
74
+
75
+
57
76
  instantiateServiceProvider(pServiceType, pOptions, pCustomServiceHash)
58
77
  {
59
78
  // Instantiate the service
@@ -1,5 +1,5 @@
1
1
  /**
2
- * MetaTemplate String Parser
2
+ * String Parser
3
3
  * @author Steven Velozo <steven@velozo.com>
4
4
  * @description Parse a string, properly processing each matched token in the word tree.
5
5
  */
@@ -32,33 +32,13 @@ class StringParser
32
32
  Output: '',
33
33
  OutputBuffer: '',
34
34
 
35
- Pattern: false,
35
+ Pattern: {},
36
36
 
37
37
  PatternMatch: false,
38
- PatternMatchOutputBuffer: ''
38
+ PatternMatchEnd: false
39
39
  });
40
40
  }
41
41
 
42
- /**
43
- * Assign a node of the parser tree to be the next potential match.
44
- * If the node has a PatternEnd property, it is a valid match and supercedes the last valid match (or becomes the initial match).
45
- * @method assignNode
46
- * @param {Object} pNode - A node on the parse tree to assign
47
- * @param {Object} pParserState - The state object for the current parsing task
48
- * @private
49
- */
50
- assignNode (pNode, pParserState)
51
- {
52
- pParserState.PatternMatch = pNode;
53
-
54
- // If the pattern has a END we can assume it has a parse function...
55
- if (pParserState.PatternMatch.hasOwnProperty('PatternEnd'))
56
- {
57
- // ... this is the legitimate start of a pattern.
58
- pParserState.Pattern = pParserState.PatternMatch;
59
- }
60
- }
61
-
62
42
  /**
63
43
  * Append a character to the output buffer in the parser state.
64
44
  * This output buffer is used when a potential match is being explored, or a match is being explored.
@@ -84,80 +64,124 @@ class StringParser
84
64
  pParserState.OutputBuffer = '';
85
65
  }
86
66
 
67
+ resetOutputBuffer (pParserState)
68
+ {
69
+ // Flush the output buffer.
70
+ this.flushOutputBuffer(pParserState);
71
+ // End pattern mode
72
+ pParserState.Pattern = false;
73
+ pParserState.PatternStartNode = false;
74
+ pParserState.StartPatternMatchComplete = false;
75
+ pParserState.EndPatternMatchBegan = false;
76
+ pParserState.PatternMatch = false;
77
+
78
+ return true;
79
+ }
80
+
87
81
  /**
88
- * Check if the pattern has ended. If it has, properly flush the buffer and start looking for new patterns.
89
- * @method checkPatternEnd
82
+ * Parse a character in the buffer.
83
+ * @method parseCharacter
84
+ * @param {string} pCharacter - The character to append
90
85
  * @param {Object} pParserState - The state object for the current parsing task
91
86
  * @private
92
87
  */
93
- checkPatternEnd (pParserState, pData)
88
+ parseCharacter (pCharacter, pParserState, pData)
94
89
  {
95
- if ((pParserState.OutputBuffer.length >= pParserState.Pattern.PatternEnd.length+pParserState.Pattern.PatternStart.length) &&
96
- (pParserState.OutputBuffer.substr(-pParserState.Pattern.PatternEnd.length) === pParserState.Pattern.PatternEnd))
90
+ // If we are already in a pattern match traversal
91
+ if (pParserState.PatternMatch)
97
92
  {
98
- // ... this is the end of a pattern, cut off the end tag and parse it.
99
- // Trim the start and end tags off the output buffer now
100
- if (pParserState.Pattern.isAsync)
93
+ // If the pattern is still matching the start and we haven't passed the buffer
94
+ if (!pParserState.StartPatternMatchComplete && pParserState.Pattern.hasOwnProperty(pCharacter))
101
95
  {
102
- console.log(`Precedent ERROR: Async template detected for pattern ${pParserState.Pattern.PatternStart} ... ${pParserState.Pattern.PatternEnd} but the template engine is being run in non-async mode.`);
103
- this.OutputBuffer = '';
104
- // Flush the output buffer.
105
- this.flushOutputBuffer(pParserState);
106
- // End pattern mode
107
- pParserState.Pattern = false;
108
- pParserState.PatternMatch = false;
96
+ pParserState.Pattern = pParserState.Pattern[pCharacter];
97
+ this.appendOutputBuffer(pCharacter, pParserState);
109
98
  }
110
- else
99
+ else if (pParserState.EndPatternMatchBegan)
111
100
  {
112
- pParserState.OutputBuffer = pParserState.Pattern.Parse(pParserState.OutputBuffer.substr(pParserState.Pattern.PatternStart.length, pParserState.OutputBuffer.length - (pParserState.Pattern.PatternStart.length+pParserState.Pattern.PatternEnd.length)), pData);
113
- // Flush the output buffer.
114
- this.flushOutputBuffer(pParserState);
115
- // End pattern mode
116
- pParserState.Pattern = false;
117
- pParserState.PatternMatch = false;
101
+ if (pParserState.Pattern.PatternEnd.hasOwnProperty(pCharacter))
102
+ {
103
+ // This leaf has a PatternEnd tree, so we will wait until that end is met.
104
+ pParserState.Pattern = pParserState.Pattern.PatternEnd[pCharacter];
105
+ // Flush the output buffer.
106
+ this.appendOutputBuffer(pCharacter, pParserState);
107
+ // If this last character is the end of the pattern, parse it.
108
+ if (pParserState.Pattern.hasOwnProperty('Parse'))
109
+ {
110
+ // Run the function
111
+ pParserState.OutputBuffer = pParserState.Pattern.Parse(pParserState.OutputBuffer.substr(pParserState.Pattern.PatternStartString.length, pParserState.OutputBuffer.length - (pParserState.Pattern.PatternStartString.length+pParserState.Pattern.PatternEndString.length)), pData);
112
+ return this.resetOutputBuffer(pParserState);
113
+ }
114
+ }
115
+ else if (pParserState.PatternStartNode.PatternEnd.hasOwnProperty(pCharacter))
116
+ {
117
+ // We broke out of the end -- see if this is a new start of the end.
118
+ pParserState.Pattern = pParserState.PatternStartNode.PatternEnd[pCharacter];
119
+ this.appendOutputBuffer(pCharacter, pParserState);
120
+ }
121
+ else
122
+ {
123
+ pParserState.EndPatternMatchBegan = false;
124
+ this.appendOutputBuffer(pCharacter, pParserState);
125
+ }
118
126
  }
119
- }
120
- }
121
-
122
- checkPatternEndAsync (pParserState, pData, fCallback)
123
- {
124
- if ((pParserState.OutputBuffer.length >= pParserState.Pattern.PatternEnd.length+pParserState.Pattern.PatternStart.length) &&
125
- (pParserState.OutputBuffer.substr(-pParserState.Pattern.PatternEnd.length) === pParserState.Pattern.PatternEnd))
126
- {
127
- // ... this is the end of a pattern, cut off the end tag and parse it.
128
- // Trim the start and end tags off the output buffer now
129
- if (pParserState.Pattern.isAsync)
127
+ else if (pParserState.Pattern.hasOwnProperty('PatternEnd'))
130
128
  {
131
- return pParserState.Pattern.Parse(pParserState.OutputBuffer.substr(pParserState.Pattern.PatternStart.length, pParserState.OutputBuffer.length - (pParserState.Pattern.PatternStart.length+pParserState.Pattern.PatternEnd.length)), pData,
132
- (pError, pAsyncOutput) =>
129
+ if (!pParserState.StartPatternMatchComplete)
130
+ {
131
+ pParserState.StartPatternMatchComplete = true;
132
+ pParserState.PatternStartNode = pParserState.Pattern;
133
+ }
134
+
135
+ this.appendOutputBuffer(pCharacter, pParserState);
136
+
137
+ if (pParserState.Pattern.PatternEnd.hasOwnProperty(pCharacter))
138
+ {
139
+ // This is the first character of the end pattern.
140
+ pParserState.EndPatternMatchBegan = true;
141
+ // This leaf has a PatternEnd tree, so we will wait until that end is met.
142
+ pParserState.Pattern = pParserState.Pattern.PatternEnd[pCharacter];
143
+ // If this last character is the end of the pattern, parse it.
144
+ if (pParserState.Pattern.hasOwnProperty('Parse'))
133
145
  {
134
- if (pError)
146
+ if (pParserState.Pattern.isAsync)
135
147
  {
136
- console.log(`Precedent ERROR: Async template error happened parsing ${pParserState.Pattern.PatternStart} ... ${pParserState.Pattern.PatternEnd}: ${pError}`);
148
+ this.log.error(`MetaTemplate: The pattern ${pParserState.Pattern.PatternStartString} is asynchronous and cannot be used in a synchronous parser.`);
149
+ this.resetOutputBuffer(pParserState);
137
150
  }
138
-
139
- pParserState.OutputBuffer = pAsyncOutput;
140
- // Flush the output buffer.
141
- this.flushOutputBuffer(pParserState);
142
- // End pattern mode
143
- pParserState.Pattern = false;
144
- pParserState.PatternMatch = false;
145
-
146
- return fCallback();
147
- });
151
+ else
152
+ {
153
+ // Run the t*mplate function
154
+ pParserState.OutputBuffer = pParserState.Pattern.Parse(pParserState.OutputBuffer.substr(pParserState.Pattern.PatternStartString.length, pParserState.OutputBuffer.length - (pParserState.Pattern.PatternStartString.length+pParserState.Pattern.PatternEndString.length)), pData);
155
+ return this.resetOutputBuffer(pParserState);
156
+ }
157
+ }
158
+ }
148
159
  }
149
160
  else
150
161
  {
151
- pParserState.OutputBuffer = pParserState.Pattern.Parse(pParserState.OutputBuffer.substr(pParserState.Pattern.PatternStart.length, pParserState.OutputBuffer.length - (pParserState.Pattern.PatternStart.length+pParserState.Pattern.PatternEnd.length)), pData);
152
- // Flush the output buffer.
153
- this.flushOutputBuffer(pParserState);
154
- // End pattern mode
155
- pParserState.Pattern = false;
156
- pParserState.PatternMatch = false;
162
+ // We are in a pattern start but didn't match one; reset and start trying again from this character.
163
+ this.resetOutputBuffer(pParserState);
157
164
  }
158
165
  }
159
-
160
- return fCallback();
166
+ // If we aren't in a pattern match or pattern, and this isn't the start of a new pattern (RAW mode)....
167
+ if (!pParserState.PatternMatch)
168
+ {
169
+ // This may be the start of a new pattern....
170
+ if (pParserState.ParseTree.hasOwnProperty(pCharacter))
171
+ {
172
+ // ... assign the root node as the matched node.
173
+ this.resetOutputBuffer(pParserState);
174
+ this.appendOutputBuffer(pCharacter, pParserState);
175
+ pParserState.Pattern = pParserState.ParseTree[pCharacter];
176
+ pParserState.PatternMatch = true;
177
+ return true;
178
+ }
179
+ else
180
+ {
181
+ this.appendOutputBuffer(pCharacter, pParserState);
182
+ }
183
+ }
184
+ return false;
161
185
  }
162
186
 
163
187
  /**
@@ -167,70 +191,139 @@ class StringParser
167
191
  * @param {Object} pParserState - The state object for the current parsing task
168
192
  * @private
169
193
  */
170
- parseCharacter (pCharacter, pParserState, pData)
194
+ parseCharacterAsync (pCharacter, pParserState, pData, fCallback)
171
195
  {
172
- // (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....
173
- if (!pParserState.PatternMatch && pParserState.ParseTree.hasOwnProperty(pCharacter))
174
- {
175
- // ... assign the node as the matched node.
176
- this.assignNode(pParserState.ParseTree[pCharacter], pParserState);
177
- this.appendOutputBuffer(pCharacter, pParserState);
178
- }
179
- // (2) If we are in a pattern match (actively seeing if this is part of a new pattern token)
180
- else if (pParserState.PatternMatch)
196
+ // If we are already in a pattern match traversal
197
+ if (pParserState.PatternMatch)
181
198
  {
182
- // If the pattern has a subpattern with this key
183
- if (pParserState.PatternMatch.hasOwnProperty(pCharacter))
199
+ // If the pattern is still matching the start and we haven't passed the buffer
200
+ if (!pParserState.StartPatternMatchComplete && pParserState.Pattern.hasOwnProperty(pCharacter))
184
201
  {
185
- // Continue matching patterns.
186
- this.assignNode(pParserState.PatternMatch[pCharacter], pParserState);
202
+ pParserState.Pattern = pParserState.Pattern[pCharacter];
203
+ this.appendOutputBuffer(pCharacter, pParserState);
187
204
  }
188
- this.appendOutputBuffer(pCharacter, pParserState);
189
- if (pParserState.Pattern)
205
+ else if (pParserState.EndPatternMatchBegan)
190
206
  {
191
- // ... Check if this is the end of the pattern (if we are matching a valid pattern)...
192
- this.checkPatternEnd(pParserState, pData);
207
+ if (pParserState.Pattern.PatternEnd.hasOwnProperty(pCharacter))
208
+ {
209
+ // This leaf has a PatternEnd tree, so we will wait until that end is met.
210
+ pParserState.Pattern = pParserState.Pattern.PatternEnd[pCharacter];
211
+ // Flush the output buffer.
212
+ this.appendOutputBuffer(pCharacter, pParserState);
213
+ // If this last character is the end of the pattern, parse it.
214
+ if (pParserState.Pattern.hasOwnProperty('Parse'))
215
+ {
216
+ // ... this is the end of a pattern, cut off the end tag and parse it.
217
+ // Trim the start and end tags off the output buffer now
218
+ if (pParserState.Pattern.isAsync)
219
+ {
220
+ // Run the function
221
+ return pParserState.Pattern.Parse(pParserState.OutputBuffer.substr(pParserState.Pattern.PatternStartString.length, pParserState.OutputBuffer.length - (pParserState.Pattern.PatternStartString.length+pParserState.Pattern.PatternEndString.length)), pData,
222
+ (pError, pAsyncOutput) =>
223
+ {
224
+ if (pError)
225
+ {
226
+ console.log(`Precedent ERROR: Async template error happened parsing ${pParserState.Pattern.PatternStart} ... ${pParserState.Pattern.PatternEnd}: ${pError}`);
227
+ }
228
+
229
+ pParserState.OutputBuffer = pAsyncOutput;
230
+ this.resetOutputBuffer(pParserState);
231
+ return fCallback();
232
+ });
233
+ }
234
+ else
235
+ {
236
+ // Run the t*mplate function
237
+ pParserState.OutputBuffer = pParserState.Pattern.Parse(pParserState.OutputBuffer.substr(pParserState.Pattern.PatternStartString.length, pParserState.OutputBuffer.length - (pParserState.Pattern.PatternStartString.length+pParserState.Pattern.PatternEndString.length)), pData);
238
+ this.resetOutputBuffer(pParserState);
239
+ return fCallback();
240
+ }
241
+ }
242
+ }
243
+ else if (pParserState.PatternStartNode.PatternEnd.hasOwnProperty(pCharacter))
244
+ {
245
+ // We broke out of the end -- see if this is a new start of the end.
246
+ pParserState.Pattern = pParserState.PatternStartNode.PatternEnd[pCharacter];
247
+ this.appendOutputBuffer(pCharacter, pParserState);
248
+ }
249
+ else
250
+ {
251
+ pParserState.EndPatternMatchBegan = false;
252
+ this.appendOutputBuffer(pCharacter, pParserState);
253
+ }
193
254
  }
194
- }
195
- // (3) If we aren't in a pattern match or pattern, and this isn't the start of a new pattern (RAW mode)....
196
- else
197
- {
198
- pParserState.Output += pCharacter;
199
- }
200
- }
255
+ else if (pParserState.Pattern.hasOwnProperty('PatternEnd'))
256
+ {
257
+ if (!pParserState.StartPatternMatchComplete)
258
+ {
259
+ pParserState.StartPatternMatchComplete = true;
260
+ pParserState.PatternStartNode = pParserState.Pattern;
261
+ }
201
262
 
202
- parseCharacterAsync (pCharacter, pParserState, pData, fCallback)
203
- {
204
- // (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....
205
- if (!pParserState.PatternMatch && pParserState.ParseTree.hasOwnProperty(pCharacter))
206
- {
207
- // ... assign the node as the matched node.
208
- this.assignNode(pParserState.ParseTree[pCharacter], pParserState);
209
- this.appendOutputBuffer(pCharacter, pParserState);
263
+ this.appendOutputBuffer(pCharacter, pParserState);
264
+
265
+ if (pParserState.Pattern.PatternEnd.hasOwnProperty(pCharacter))
266
+ {
267
+ // This is the first character of the end pattern.
268
+ pParserState.EndPatternMatchBegan = true;
269
+ // This leaf has a PatternEnd tree, so we will wait until that end is met.
270
+ pParserState.Pattern = pParserState.Pattern.PatternEnd[pCharacter];
271
+ // If this last character is the end of the pattern, parse it.
272
+ if (pParserState.Pattern.hasOwnProperty('Parse'))
273
+ {
274
+ // ... this is the end of a pattern, cut off the end tag and parse it.
275
+ // Trim the start and end tags off the output buffer now
276
+ if (pParserState.Pattern.isAsync)
277
+ {
278
+ // Run the function
279
+ return pParserState.Pattern.Parse(pParserState.OutputBuffer.substr(pParserState.Pattern.PatternStartString.length, pParserState.OutputBuffer.length - (pParserState.Pattern.PatternStartString.length+pParserState.Pattern.PatternEndString.length)), pData,
280
+ (pError, pAsyncOutput) =>
281
+ {
282
+ if (pError)
283
+ {
284
+ console.log(`Precedent ERROR: Async template error happened parsing ${pParserState.Pattern.PatternStart} ... ${pParserState.Pattern.PatternEnd}: ${pError}`);
285
+ }
286
+
287
+ pParserState.OutputBuffer = pAsyncOutput;
288
+ this.resetOutputBuffer(pParserState);
289
+ return fCallback();
290
+ });
291
+ }
292
+ else
293
+ {
294
+ // Run the t*mplate function
295
+ pParserState.OutputBuffer = pParserState.Pattern.Parse(pParserState.OutputBuffer.substr(pParserState.Pattern.PatternStartString.length, pParserState.OutputBuffer.length - (pParserState.Pattern.PatternStartString.length+pParserState.Pattern.PatternEndString.length)), pData);
296
+ this.resetOutputBuffer(pParserState);
297
+ return fCallback();
298
+ }
299
+ }
300
+ }
301
+ }
302
+ else
303
+ {
304
+ // We are in a pattern start but didn't match one; reset and start trying again from this character.
305
+ this.resetOutputBuffer(pParserState);
306
+ return fCallback();
307
+ }
210
308
  }
211
- // (2) If we are in a pattern match (actively seeing if this is part of a new pattern token)
212
- else if (pParserState.PatternMatch)
309
+ // If we aren't in a pattern match or pattern, and this isn't the start of a new pattern (RAW mode)....
310
+ if (!pParserState.PatternMatch)
213
311
  {
214
- // If the pattern has a subpattern with this key
215
- if (pParserState.PatternMatch.hasOwnProperty(pCharacter))
312
+ // This may be the start of a new pattern....
313
+ if (pParserState.ParseTree.hasOwnProperty(pCharacter))
216
314
  {
217
- // Continue matching patterns.
218
- this.assignNode(pParserState.PatternMatch[pCharacter], pParserState);
315
+ // ... assign the root node as the matched node.
316
+ this.resetOutputBuffer(pParserState);
317
+ this.appendOutputBuffer(pCharacter, pParserState);
318
+ pParserState.Pattern = pParserState.ParseTree[pCharacter];
319
+ pParserState.PatternMatch = true;
219
320
  }
220
- this.appendOutputBuffer(pCharacter, pParserState);
221
- if (pParserState.Pattern)
321
+ else
222
322
  {
223
- // ... Check if this is the end of the pattern (if we are matching a valid pattern)...
224
- return this.checkPatternEndAsync(pParserState, pData, fCallback);
323
+ this.appendOutputBuffer(pCharacter, pParserState);
225
324
  }
226
325
  }
227
- // (3) If we aren't in a pattern match or pattern, and this isn't the start of a new pattern (RAW mode)....
228
- else
229
- {
230
- pParserState.Output += pCharacter;
231
- }
232
-
233
- return fCallback(null);
326
+ return fCallback();
234
327
  }
235
328
 
236
329
  /**
@@ -261,6 +354,7 @@ class StringParser
261
354
  {
262
355
  // This is the async mode
263
356
  let tmpParserState = this.newParserState(pParseTree);
357
+ tmpParserState.Asynchronous = true;
264
358
 
265
359
  this.eachLimit(pString, 1,
266
360
  (pCharacter, fCharacterCallback) =>
@@ -1,5 +1,5 @@
1
1
  /**
2
- * MetaTemplate Word Tree
2
+ * Word Tree
3
3
  * @author Steven Velozo <steven@velozo.com>
4
4
  * @description Create a tree (directed graph) of Javascript objects, one character per object.
5
5
  */
@@ -19,78 +19,101 @@ class WordTree
19
19
  * @method addChild
20
20
  * @param {Object} pTree - A parse tree to push the characters into
21
21
  * @param {string} pPattern - The string to add to the tree
22
- * @param {number} pIndex - The index of the character in the pattern
23
22
  * @returns {Object} The resulting leaf node that was added (or found)
24
23
  * @private
25
24
  */
26
- addChild (pTree, pPattern, pIndex)
25
+ addChild (pTree, pPattern)
27
26
  {
28
- if (!pTree.hasOwnProperty(pPattern[pIndex]))
29
- pTree[pPattern[pIndex]] = {};
27
+ if (!pTree.hasOwnProperty(pPattern))
28
+ {
29
+ pTree[pPattern] = {};
30
+ }
30
31
 
31
- return pTree[pPattern[pIndex]];
32
+ return pTree[pPattern];
33
+ }
34
+
35
+ /**
36
+ * Add a child character to a Parse Tree PatternEnd subtree
37
+ * @method addChild
38
+ * @param {Object} pTree - A parse tree to push the characters into
39
+ * @param {string} pPattern - The string to add to the tree
40
+ * @returns {Object} The resulting leaf node that was added (or found)
41
+ * @private
42
+ */
43
+ addEndChild (pTree, pPattern)
44
+ {
45
+ if (!pTree.hasOwnProperty('PatternEnd'))
46
+ {
47
+ pTree.PatternEnd = {};
48
+ }
49
+
50
+ pTree.PatternEnd[pPattern] = {};
51
+
52
+ return pTree.PatternEnd[pPattern];
32
53
  }
33
54
 
34
55
  /** Add a Pattern to the Parse Tree
35
56
  * @method addPattern
36
57
  * @param {Object} pPatternStart - The starting string for the pattern (e.g. "${")
37
58
  * @param {string} pPatternEnd - The ending string for the pattern (e.g. "}")
38
- * @param {number} pParser - The function to parse if this is the matched pattern, once the Pattern End is met. If this is a string, a simple replacement occurs.
59
+ * @param {function} fParser - The function to parse if this is the matched pattern, once the Pattern End is met. If this is a string, a simple replacement occurs.
39
60
  * @return {bool} True if adding the pattern was successful
40
61
  */
41
- addPattern (pPatternStart, pPatternEnd, pParser)
62
+ addPattern (pPatternStart, pPatternEnd, fParser)
42
63
  {
43
64
  if (pPatternStart.length < 1)
65
+ {
44
66
  return false;
67
+ }
45
68
 
46
69
  if ((typeof(pPatternEnd) === 'string') && (pPatternEnd.length < 1))
70
+ {
47
71
  return false;
72
+ }
48
73
 
49
74
  let tmpLeaf = this.ParseTree;
50
75
 
51
76
  // Add the tree of leaves iteratively
52
77
  for (var i = 0; i < pPatternStart.length; i++)
53
- tmpLeaf = this.addChild(tmpLeaf, pPatternStart, i);
54
-
55
- tmpLeaf.PatternStart = pPatternStart;
56
- tmpLeaf.PatternEnd = ((typeof(pPatternEnd) === 'string') && (pPatternEnd.length > 0)) ? pPatternEnd : pPatternStart;
57
- tmpLeaf.Parse = (typeof(pParser) === 'function') ? pParser :
58
- (typeof(pParser) === 'string') ? () => { return pParser; } :
78
+ {
79
+ tmpLeaf = this.addChild(tmpLeaf, pPatternStart[i], i);
80
+ }
81
+
82
+ if (!tmpLeaf.hasOwnProperty('PatternEnd'))
83
+ {
84
+ tmpLeaf.PatternEnd = {};
85
+ }
86
+
87
+ let tmpPatternEnd = (typeof(pPatternEnd) === 'string') ? pPatternEnd : pPatternStart;
88
+ for (let i = 0; i < tmpPatternEnd.length; i++)
89
+ {
90
+ tmpLeaf = this.addEndChild(tmpLeaf, tmpPatternEnd[i], i);
91
+ }
92
+
93
+ tmpLeaf.PatternStartString = pPatternStart;
94
+ tmpLeaf.PatternEndString = tmpPatternEnd;
95
+ tmpLeaf.Parse = (typeof(fParser) === 'function') ? fParser :
96
+ (typeof(fParser) === 'string') ? () => { return fParser; } :
59
97
  (pData) => { return pData; };
60
- tmpLeaf.isPromise = false;
61
98
 
62
- return true;
99
+ return tmpLeaf;
63
100
  }
64
101
 
65
- /** Add a Pattern to the Parse Tree (asynchronous)
102
+
103
+ /** Add a Pattern to the Parse Tree
66
104
  * @method addPattern
67
105
  * @param {Object} pPatternStart - The starting string for the pattern (e.g. "${")
68
106
  * @param {string} pPatternEnd - The ending string for the pattern (e.g. "}")
69
- * @param {number} pParserAsync - The function (with an asynchronous callback) to parse if this is the matched pattern, once the Pattern End is met. If this is a string, a simple replacement occurs.
107
+ * @param {function} fParser - The function to parse if this is the matched pattern, once the Pattern End is met. If this is a string, a simple replacement occurs.
70
108
  * @return {bool} True if adding the pattern was successful
71
109
  */
72
- addPatternAsync (pPatternStart, pPatternEnd, pParserAsync)
110
+ addPatternAsync (pPatternStart, pPatternEnd, fParser)
73
111
  {
74
- if (pPatternStart.length < 1)
75
- return false;
76
-
77
- if ((typeof(pPatternEnd) === 'string') && (pPatternEnd.length < 1))
78
- return false;
79
-
80
- let tmpLeaf = this.ParseTree;
81
-
82
- // Add the tree of leaves iteratively
83
- for (var i = 0; i < pPatternStart.length; i++)
84
- tmpLeaf = this.addChild(tmpLeaf, pPatternStart, i);
85
-
86
- tmpLeaf.PatternStart = pPatternStart;
87
- tmpLeaf.PatternEnd = ((typeof(pPatternEnd) === 'string') && (pPatternEnd.length > 0)) ? pPatternEnd : pPatternStart;
88
- tmpLeaf.Parse = (typeof(pParserAsync) === 'function') ? pParserAsync :
89
- (typeof(pParserAsync) === 'string') ? (pHash, pData, fCallback) => { fCallback(pParserPromise); } :
90
- (pHash, pData, fCallback) => { return fCallback(pHash); };
91
- tmpLeaf.isAsync = true;
92
-
93
- return true;
112
+ let tmpLeaf = this.addPattern(pPatternStart, pPatternEnd, fParser);
113
+ if (tmpLeaf)
114
+ {
115
+ tmpLeaf.isAsync = true;
116
+ }
94
117
  }
95
118
  }
96
119
 
@@ -138,8 +138,11 @@ suite
138
138
  testFable.serviceManager.addServiceType('SimpleService', SimpleService);
139
139
 
140
140
  let tmpService = testFable.serviceManager.instantiateServiceProviderWithoutRegistration('SimpleService', {SomeOption: true}, 'SimpleService-99');
141
+ let tmpServiceFromPrototype = testFable.serviceManager.instantiateServiceProviderFromPrototype('SimpleService', {SomeOption: true}, 'SimpleService-100', SimpleService);
141
142
 
142
143
  Expect(testFable.services.SimpleService['SimpleService-99']).to.be.an('undefined');
144
+ Expect(testFable.services.SimpleService['SimpleService-100']).to.be.an('object');
145
+ Expect(tmpServiceFromPrototype).to.be.an('object');
143
146
 
144
147
  Expect(tmpService).to.be.an('object');
145
148
  }
@@ -198,9 +198,6 @@ suite
198
198
  'Match this <<> and this <<here> please.',
199
199
  'Match this MEDIUM_MATCH and this MEDIUM_MATCH please.',
200
200
 
201
- 'Match this <<EXTRA> and this <<here> please.',
202
- 'Match this MEDIUM_MATCH and this MEDIUM_MATCH please.',
203
-
204
201
  'Match this <<EXTRALONG> and this <<here> please.',
205
202
  'Match this EXTRA_LONG_MATCH and this MEDIUM_MATCH please.',
206
203