spyne 0.18.2 → 0.19.0

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.
@@ -1,5 +1,6 @@
1
1
  import {includes, __, ifElse, path, prop, reject, is, isNil, isEmpty} from 'ramda';
2
2
 
3
+
3
4
  /**
4
5
  * @module DomElTemplate
5
6
  * @type util
@@ -133,8 +134,11 @@ import {includes, __, ifElse, path, prop, reject, is, isNil, isEmpty} from 'ramd
133
134
  */
134
135
 
135
136
  export class DomElementTemplate {
136
- constructor(template, data) {
137
+ constructor(template, data={}) {
137
138
  this.template = this.formatTemplate(template);
139
+ this.isProxyData = data.__cms__isProxy === true;
140
+
141
+
138
142
 
139
143
  const checkForArrayData = ()=>{
140
144
  if (is(Array, data) === true) {
@@ -149,40 +153,60 @@ export class DomElementTemplate {
149
153
 
150
154
  this.templateData = data;
151
155
 
152
-
153
156
  let strArr = DomElementTemplate.getStringArray(this.template);
154
157
 
155
-
156
158
  let strMatches = this.template.match(DomElementTemplate.findTmplLoopsRE());
157
159
  strMatches = strMatches === null ? [] : strMatches;
158
160
 
159
161
  const parseTmplLoopsRE = DomElementTemplate.parseTmplLoopsRE();
162
+
160
163
  const parseTmplLoopFn = this.parseTheTmplLoop.bind(this);
161
- const mapTmplLoop = (str, data) => str.replace(parseTmplLoopsRE, parseTmplLoopFn);
162
- const findTmplLoopsPred = includes(__, strMatches);
163
164
 
165
+ const mapTmplLoop = (str, data) => {
166
+ return str.replace(parseTmplLoopsRE, parseTmplLoopFn);
167
+ }
168
+
169
+ const findTmplLoopsPred = includes(__, strMatches);
164
170
  const checkForMatches = ifElse(
165
- findTmplLoopsPred,
166
- mapTmplLoop,
167
- this.addParams.bind(this));
171
+ findTmplLoopsPred,
172
+ mapTmplLoop,
173
+ this.addParams.bind(this));
168
174
 
169
175
  this.finalArr = strArr.map(checkForMatches);
170
176
 
171
177
  }
172
178
 
179
+ static isPrimitiveTag(str){
180
+ return /({{\.\*?}})/.test(str);;
181
+ }
182
+
183
+ // FIND CORRECT NESTED DATA
184
+ static getNestedDataReducer(data={}, param=""){
185
+ const dataReducer = (nestedData, str) =>{
186
+ if (nestedData[str]){
187
+ return nestedData[str];
188
+ }
189
+ return nestedData;
190
+ }
191
+ return /(\.)/gm.test(String(param)) ? String(param).split('.').reduce(dataReducer,data) : data[param];
192
+ }
193
+
173
194
  static getStringArray(template) {
174
195
  let strArr = template.split(DomElementTemplate.findTmplLoopsRE());
175
196
  const emptyRE = /^([\\n\s\W]+)$/;
176
197
  const filterOutEmptyStrings = s => s.match(emptyRE);
177
- return reject(filterOutEmptyStrings, strArr);
198
+ const finalStr = reject(filterOutEmptyStrings, strArr);
199
+
200
+ return finalStr;
201
+
178
202
  }
179
203
 
180
204
  static findTmplLoopsRE() {
181
- return /({{#\w+}}[\w\n\s\W]+?{{\/\w+}})/gm;
205
+ return /({{#[\w.]+}}[\w\n\s\W]+?{{\/[\w.]+}})/gm;
182
206
  }
183
207
 
184
208
  static parseTmplLoopsRE() {
185
- return /({{#(\w+)}})([\w\n\s\W]+?)({{\/\2}})/gm;
209
+ return /({{#([\w.]+)}})([\w\n\s\W]+?)({{\/\2}})/gm;
186
210
  }
187
211
 
188
212
  static swapParamsForTagsRE() {
@@ -196,10 +220,10 @@ export class DomElementTemplate {
196
220
  }
197
221
 
198
222
 
199
- /**
200
- *
201
- * @desc Returns a document fragment generated from the template and any added data.
202
- */
223
+ /**
224
+ *
225
+ * @desc Returns a document fragment generated from the template and any added data.
226
+ */
203
227
 
204
228
 
205
229
  renderDocFrag() {
@@ -207,7 +231,7 @@ export class DomElementTemplate {
207
231
  const isTableSubTag = /^([^>]*?)(<){1}(\b)(thead|col|colgroup|tbody|td|tfoot|tr|th)(\b)([^\0]*)$/.test(html);
208
232
  const el = isTableSubTag ? html : document.createRange().createContextualFragment(html);
209
233
 
210
- window.setTimeout(this.removeThis(), 2);
234
+ window.setTimeout(this.removeThis(), 2);
211
235
  return el;
212
236
 
213
237
  }
@@ -233,52 +257,97 @@ export class DomElementTemplate {
233
257
  }
234
258
 
235
259
  addParams(str) {
236
- //console.time(this.tempL+'9')
237
260
  const re = /(\.)/gm;
238
-
239
261
  const replaceTags = (str, p1, p2, p3) => {
240
- if (re.test(p2) === false && this.templateData[p2] !==undefined){
241
- return this.templateData[p2];
242
- }
243
- return this.getDataValFromPathStr(p2, this.templateData);
262
+ return DomElementTemplate.getNestedDataReducer(this.templateData, p2);
244
263
  };
245
-
246
- return str.replace(DomElementTemplate.swapParamsForTagsRE(), replaceTags);
264
+ return str.replace(DomElementTemplate.swapParamsForTagsRE(), replaceTags);
247
265
 
248
266
  }
249
267
 
250
- parseTheTmplLoop(str, p1, p2, p3) {
251
268
 
252
- //console.time(this.tempL+'5b')
269
+
270
+
271
+ parseTheTmplLoop(str, p1, p2, p3) {
272
+ const dotConverter = str=>`${str.replace(/(\.)/g, "][")}`
253
273
  const reDot = /(\.)/gm;
254
274
  const subStr = p3;
255
- let elData = this.templateData[p2];
256
- const parseString = (item, str) => {
275
+
276
+ const dataReducer = (acc, str) =>{
277
+ acc = acc[str];
278
+ return acc;
279
+ }
280
+
281
+
282
+ let elData = DomElementTemplate.getNestedDataReducer(this.templateData, p2);
283
+
284
+ const arrayStringToObjAdapter = (d,str, i)=>{
285
+
286
+ // IF {{.}} RUN parseString
287
+ if (DomElementTemplate.isPrimitiveTag(str)){
288
+ return parseString(d, str, i);
289
+ }
290
+
291
+ // CREATE DATA OBJ -- CHECK TO ADD PROXY VALUES
292
+ const createDataObj = ()=>{
293
+ const spyneLoopKey = d;
294
+ const loopIndex = i;
295
+ const loopNum = i+1;
296
+
297
+ if (this.isProxyData) {
298
+ const __cms__dataId = elData.__cms__dataId;
299
+ const keyIdStr = `__cms__keyFor_${d}`
300
+ const origKey = elData[keyIdStr];
301
+ return {spyneLoopKey, __cms__dataId, origKey, loopIndex, loopNum, d}
302
+
303
+ }
304
+ return {spyneLoopKey, loopIndex, loopNum};
305
+ }
306
+
307
+ return parseObject(createDataObj(), str, i);
308
+ }
309
+
310
+ const parseString = (item, str, index, origIndex) => {
257
311
  return str.replace(DomElementTemplate.swapParamsForTagsRE(), item);
258
312
  };
259
- const parseObject = (obj, str) => {
313
+
314
+
315
+ // PARSING ARRAYS AND OBJECTS
316
+ const parseObject = (obj, str, i) => {
317
+ /// LOOP NUMBER VALUES AUTO ADDED
318
+
319
+ //const loopIndex = i;
320
+ //const loopNum = i+1;
321
+
260
322
  const loopObj = (str, p1, p2) => {
261
323
  // DOT SYNTAX CHECK
324
+ const hash = {
325
+ loopIndex: i,
326
+ loopNum: i+1
327
+ }
328
+
329
+ // IF {{.}}
262
330
  if (reDot.test(p2) === false && obj[p2] !==undefined) {
263
- return obj[p2]
331
+ return hash[p2] !== undefined ? hash[p2] : obj[p2]
264
332
  }
265
333
 
266
- return this.getDataValFromPathStr(p2, obj);
334
+ const dataReducedVal = this.getDataValFromPathStr(p2, obj);
335
+ return hash[p2] !== undefined ? hash[p2] : dataReducedVal
267
336
  };
268
337
  return str.replace(DomElementTemplate.swapParamsForTagsRE(), loopObj);
269
338
  };
270
- const mapStringData = (d) => typeof(d) === 'string' ? parseString(d, subStr) : parseObject(d, subStr);
271
339
 
340
+ const mapStringData = (d, i) => typeof(d) === 'string' ? arrayStringToObjAdapter(d, subStr, i) : parseObject(d, subStr, i);
272
341
 
273
342
  if (isNil(elData) === true || isEmpty(elData)) {
274
343
  return '';
275
344
  }
276
345
 
277
346
  if (elData.length===undefined) {
278
- elData = [elData];
279
- }
347
+ elData = [elData];
348
+ }
280
349
 
281
- return elData.map(mapStringData).join('');
350
+ return elData.map(mapStringData).join('');
282
351
 
283
352
 
284
353
  }
@@ -155,9 +155,17 @@ export class ViewStreamElement {
155
155
  let container = isNil(d.query) ? d.node : d.query;
156
156
  let prepend = (node, item) => node.insertBefore(item, node.firstChild);
157
157
  let append = (node, item) => node.appendChild(item);
158
+ let after = (node, item) => node.after(item);
159
+
160
+ const defaultFn = prepend;
161
+ const attachTypeHash = {
162
+ 'appendChild' : append,
163
+ 'after' : after
164
+ }
158
165
  // DETERMINE WHETHER TO USE APPEND OR PREPEND
159
166
  // ON CONNECTING DOM ITEMS TO EACH OTHER
160
- let attachFunc = d.attachType === 'appendChild' ? append : prepend;
167
+ //let attachFunc = d.attachType === 'appendChild' ? append : prepend;
168
+ const attachFunc = attachTypeHash[d.attachType] || defaultFn;
161
169
  attachFunc(container, this.domItem.render());
162
170
  this.setAnimateIn(d);
163
171
  }
@@ -1,4 +1,5 @@
1
1
  import {SpyneAppProperties} from '../utils/spyne-app-properties';
2
+ import {safeClone} from '../utils/safe-clone';
2
3
  import { gc } from '../utils/gc';
3
4
  import {
4
5
  compose,
@@ -36,7 +37,8 @@ export class ViewStreamPayload {
36
37
 
37
38
  sendToDirectorStream(payload) {
38
39
  let directorStream$ = SpyneAppProperties.channelsMap.getStream('DISPATCHER');
39
- const frozenPayload = ViewStreamPayload.deepClone(payload);
40
+ const frozenPayload = safeClone(payload);
41
+ //console.log("VS PAYLOAD ",frozenPayload);
40
42
  directorStream$.next(frozenPayload);
41
43
  payload = undefined;
42
44
 
@@ -33,7 +33,7 @@ function testSelectors(cxt, str, verboseBool) {
33
33
  const elIsDomElement = compose(lte(0), defaultTo(-1),
34
34
  prop('nodeType'));
35
35
 
36
- if (elIsDomElement(el) === false) {
36
+ if (el !== null && elIsDomElement(el) === false) {
37
37
  console.warn(`Spyne Warning: the el object is not a valid single element, ${el}`);
38
38
  return;
39
39
  }
@@ -52,18 +52,37 @@ function testSelectors(cxt, str, verboseBool) {
52
52
 
53
53
  function getNodeListArray(cxt, str, verboseBool=false) {
54
54
  let selector = str !== undefined ? `${cxt} ${str}` : cxt;
55
+ let isParent = false;
55
56
 
56
57
 
57
58
  const returnSelectorIfValid = (selector) => {
58
- try { document.querySelectorAll(selector) } catch (e) { return [] }
59
- return document.querySelectorAll(selector);
59
+ let arr = [];
60
+ try {
61
+ arr = document.querySelectorAll(selector)
62
+ } catch (e) { arr = [] }
63
+ try {
64
+ isParent = document.querySelector(str) === document.querySelector(cxt);
65
+ if (isParent === true){
66
+ arr = [document.querySelector(str)];
67
+ }
68
+ } catch(e){
69
+ //return [];
70
+ }
71
+ return arr;// document.querySelectorAll(selector);
60
72
  };
61
73
 
62
74
 
75
+ const elArr = returnSelectorIfValid(selector);
76
+
63
77
  if (verboseBool===true) {
64
- testSelectors(cxt, str, verboseBool);
78
+ const mainSel = isParent === true ? 'body' : cxt;
79
+ testSelectors(mainSel, str, verboseBool);
65
80
  }
66
- return returnSelectorIfValid(selector)
81
+
82
+ return elArr;
83
+
84
+
85
+
67
86
  }
68
87
 
69
88
  function setInlineCss(val, cxt, str) {
@@ -1,6 +1,7 @@
1
1
  import { baseCoreMixins } from '../utils/mixins/base-core-mixins';
2
2
  import {SpyneAppProperties} from '../utils/spyne-app-properties';
3
3
  import { deepMerge } from '../utils/deep-merge';
4
+ import {safeClone} from '../utils/safe-clone';
4
5
  import {
5
6
  findStrOrRegexMatchStr,
6
7
  getConstructorName
@@ -445,10 +446,11 @@ export class ViewStream {
445
446
  const elIsRendered = el => document.body.contains(el);
446
447
  const elIsReadyBool = propSatisfies(
447
448
  allPass([elIsRendered, elIsDomElement]), 'el');
448
-
449
449
  if (elIsReadyBool(this.props)) {
450
450
  this.updatePropsToMatchEl();
451
451
  this.postRender();
452
+ } else if(this.props.el === null){
453
+ console.error(`Spyne Error: The defined element for this ViewStream instance, ${this.constructor.name}, appears to not exist.`)
452
454
  }
453
455
  }
454
456
 
@@ -890,6 +892,13 @@ export class ViewStream {
890
892
  this.renderViewAndAttachToDom(node, 'dom', 'appendChild');
891
893
  }
892
894
 
895
+ appendToDomAfter(node){
896
+ if (this.props.el !== undefined){
897
+ console.warn(`Spyne Warning: The ViewStream, ${this.props.name}, has an element, ${this.props.el}, that is already rendered and does not need to be appendedToDomAfter. This may create unsusual side effects!`)
898
+ }
899
+ this.renderViewAndAttachToDom(node, 'dom', 'after');
900
+ }
901
+
893
902
  /**
894
903
  * Prepends the current ViewStream object to an existing dom element.
895
904
  * @param {HTMLElement} node the ViewStream child that is to be attached.
@@ -931,6 +940,10 @@ export class ViewStream {
931
940
  this.exchangeViewsWithChild(v, this.setAttachData('appendChild', query));
932
941
  }
933
942
 
943
+ appendViewAfter(v, query) {
944
+ this.exchangeViewsWithChild(v, this.setAttachData('after', query));
945
+ }
946
+
934
947
  /**
935
948
  * This method appends a child ViewStream object to a parent ViewStream object.
936
949
  * @param {ViewStream} v the ViewStream parent.
@@ -1286,7 +1299,7 @@ export class ViewStream {
1286
1299
  if (/CHANNEL_LIFECYCLE/.test(action)===false){
1287
1300
  Object.defineProperties(data, {
1288
1301
  payload: {
1289
- get: ()=> clone(pl)
1302
+ get: ()=> safeClone(pl)
1290
1303
 
1291
1304
  }
1292
1305
  })
@@ -31,8 +31,14 @@ describe('should test channel instance', () => {
31
31
  expect(props.sendCachedPayload).to.be.true;
32
32
  expect(actionsObj).to.deep.equal(finalActionsObj);
33
33
 
34
+ })
34
35
 
35
-
36
+ it('should update SpyneAppProperties doNotTrackList if doNotTrack is true', ()=>{
37
+ const channelName="CHANNEL_MY_TEST_CHANNEL";
38
+ const doNotTrack = true;
39
+ Channel.checkForNotTrackFlag({channelName, doNotTrack});
40
+ const untrackedChannelsArr = SpyneAppProperties.getUntrackedChannelsList()
41
+ expect(untrackedChannelsArr).to.deep.eq([channelName]);
36
42
  })
37
43
 
38
44
  });
@@ -64,6 +64,7 @@ describe('it should compare two objects for updated keys', () => {
64
64
 
65
65
  it('first comparison should be done against empty obj', () => {
66
66
  let compareStart = checkUpdatedKeys.compare(obj1);
67
+ console.log("compare start is ",compareStart);
67
68
  expect(compareStart.pathsChanged).to.deep.equal(['pageId', 'section']);
68
69
  });
69
70
 
@@ -39,7 +39,7 @@ describe('should test the ChannelDataPacketGenerator', () => {
39
39
  map.set(label, ChannelPayloadToTestFilters);
40
40
 
41
41
  const filterGateway = ChannelDataPacketGenerator.createFilterGateway(label, map);
42
- const pred = R.propEq('action', 'CHANNEL_ROUTE_CHANGE_EVENT');
42
+ const pred = R.propEq('CHANNEL_ROUTE_CHANGE_EVENT', 'action');
43
43
 
44
44
  const isCorrectAction = filterGateway(pred)
45
45
 
@@ -31,7 +31,7 @@ describe('DomElTemplate', () => {
31
31
  let data = {dog: {
32
32
  sound: 'woof'
33
33
  }};
34
- let template = "<h1>The dog says {{#dog}}{{sound}}{{/dog}}";
34
+ let template = "<h1>The dog says {{#dog}}{{sound}}{{/dog}}</h1>";
35
35
  let domElTemplate = new DomElementTemplate(template, data);
36
36
  let render = domElTemplate.renderDocFrag();
37
37
  expect(render.firstElementChild.innerText).to.equal('The dog says woof');
@@ -163,6 +163,23 @@ describe('DomElTemplate', () => {
163
163
  return true;
164
164
  });
165
165
 
166
+ it('DomElementTemplate should render index string value of an array',() =>{
167
+ const article = ["Usu at illum porro audire. Nam at ubique latine, vidit ocurreret pri ea, cu elitr nonumes mediocritatem nam.",
168
+ "Eu delenit meliore graecis sea. Sit id ubique commune, ius ne recusabo oportere similique, error putant usu ei.",
169
+ "Nam mutat saperet detracto eu, te ubique utamur aliquando pro. Ut verear probatus sea. Porro sonet euripidis ex est.",
170
+ "Mucius platonem eu per. Te utroque persecuti pro, error verterem scribentur no est.",
171
+ "An pro nibh salutatus, ea rebum aeterno complectitur has."];
172
+
173
+ const template = `<li>{{article.1}}</li>`;
174
+ const data = {article};
175
+ const domElTemplate = new DomElementTemplate(template, data);
176
+
177
+ const result = domElTemplate.renderToString();
178
+
179
+ expect(result).to.eq("<li>Eu delenit meliore graecis sea. Sit id ubique commune, ius ne recusabo oportere similique, error putant usu ei.</li>");
180
+
181
+ })
182
+
166
183
 
167
184
 
168
185
  });