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.
- package/.browserslistrc +1 -1
- package/dist/fable.compatible.js +66 -53
- package/dist/fable.compatible.min.js +5 -5
- package/dist/fable.compatible.min.js.map +1 -1
- package/dist/fable.js +66 -53
- package/dist/fable.min.js +4 -4
- package/dist/fable.min.js.map +1 -1
- package/gulpfile-config.json +2 -2
- package/gulpfile.js +2 -2
- package/package.json +1 -1
- package/source/Fable-ServiceManager.js +19 -0
- package/source/services/Fable-Service-MetaTemplate/MetaTemplate-StringParser.js +222 -128
- package/source/services/Fable-Service-MetaTemplate/MetaTemplate-WordTree.js +62 -39
- package/test/FableServiceManager_tests.js +3 -0
- package/test/MetaTemplating_tests.js +0 -3
package/gulpfile-config.json
CHANGED
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
|
@@ -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
|
-
*
|
|
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:
|
|
35
|
+
Pattern: {},
|
|
36
36
|
|
|
37
37
|
PatternMatch: false,
|
|
38
|
-
|
|
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
|
-
*
|
|
89
|
-
* @method
|
|
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
|
-
|
|
88
|
+
parseCharacter (pCharacter, pParserState, pData)
|
|
94
89
|
{
|
|
95
|
-
|
|
96
|
-
|
|
90
|
+
// If we are already in a pattern match traversal
|
|
91
|
+
if (pParserState.PatternMatch)
|
|
97
92
|
{
|
|
98
|
-
//
|
|
99
|
-
|
|
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
|
-
|
|
103
|
-
this.
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
|
|
132
|
-
|
|
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 (
|
|
146
|
+
if (pParserState.Pattern.isAsync)
|
|
135
147
|
{
|
|
136
|
-
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
|
|
152
|
-
|
|
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
|
-
|
|
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
|
-
|
|
194
|
+
parseCharacterAsync (pCharacter, pParserState, pData, fCallback)
|
|
171
195
|
{
|
|
172
|
-
//
|
|
173
|
-
if (
|
|
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
|
|
183
|
-
if (pParserState.
|
|
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
|
-
|
|
186
|
-
this.
|
|
202
|
+
pParserState.Pattern = pParserState.Pattern[pCharacter];
|
|
203
|
+
this.appendOutputBuffer(pCharacter, pParserState);
|
|
187
204
|
}
|
|
188
|
-
|
|
189
|
-
if (pParserState.Pattern)
|
|
205
|
+
else if (pParserState.EndPatternMatchBegan)
|
|
190
206
|
{
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
-
//
|
|
212
|
-
|
|
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
|
-
//
|
|
215
|
-
if (pParserState.
|
|
312
|
+
// This may be the start of a new pattern....
|
|
313
|
+
if (pParserState.ParseTree.hasOwnProperty(pCharacter))
|
|
216
314
|
{
|
|
217
|
-
//
|
|
218
|
-
this.
|
|
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
|
-
|
|
221
|
-
if (pParserState.Pattern)
|
|
321
|
+
else
|
|
222
322
|
{
|
|
223
|
-
|
|
224
|
-
return this.checkPatternEndAsync(pParserState, pData, fCallback);
|
|
323
|
+
this.appendOutputBuffer(pCharacter, pParserState);
|
|
225
324
|
}
|
|
226
325
|
}
|
|
227
|
-
|
|
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
|
-
*
|
|
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
|
|
25
|
+
addChild (pTree, pPattern)
|
|
27
26
|
{
|
|
28
|
-
if (!pTree.hasOwnProperty(pPattern
|
|
29
|
-
|
|
27
|
+
if (!pTree.hasOwnProperty(pPattern))
|
|
28
|
+
{
|
|
29
|
+
pTree[pPattern] = {};
|
|
30
|
+
}
|
|
30
31
|
|
|
31
|
-
return pTree[pPattern
|
|
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 {
|
|
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,
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
tmpLeaf.
|
|
58
|
-
|
|
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
|
|
99
|
+
return tmpLeaf;
|
|
63
100
|
}
|
|
64
101
|
|
|
65
|
-
|
|
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 {
|
|
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,
|
|
110
|
+
addPatternAsync (pPatternStart, pPatternEnd, fParser)
|
|
73
111
|
{
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
|