vsn 0.1.87 → 0.1.88

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vsn",
3
- "version": "0.1.87",
3
+ "version": "0.1.88",
4
4
  "description": "SEO Friendly Javascript/Typescript Framework",
5
5
  "keywords": [
6
6
  "framework",
@@ -73,8 +73,8 @@ export class ClassNode extends Node implements TreeNode {
73
73
  else
74
74
  dom.once('builtRoot', () => this.findClassElements(dom));
75
75
  }
76
- } else {
77
- await this.block.prepare(this.classScope, dom, tag, meta);
76
+ } else if (meta['PrepForSelector'] === this.fullSelector) { // Only prepare top level class if we're prepping for tag
77
+ await this.block.prepare(tag.scope, dom, tag, meta);
78
78
  }
79
79
  }
80
80
 
@@ -83,6 +83,7 @@ export class ClassNode extends Node implements TreeNode {
83
83
  for (const element of Array.from(dom.querySelectorAll(this.selector, tag))) {
84
84
  tags.push(await ClassNode.addElementClass(this._fullSelector, element as HTMLElement, dom, element[Tag.TaggedVariable] || null));
85
85
  }
86
+
86
87
  for (const childSelector of ClassNode.classChildren[this._fullSelector]) {
87
88
  const node = ClassNode.classes[`${this._fullSelector} ${childSelector}`];
88
89
  if (!node) continue;
@@ -98,6 +99,7 @@ export class ClassNode extends Node implements TreeNode {
98
99
 
99
100
  tag.createScope(true);
100
101
  const meta = this.updateMeta();
102
+ meta['PrepForSelector'] = this.fullSelector;
101
103
  await this.block.prepare(tag.scope, dom, tag, meta);
102
104
  if (hasConstruct) {
103
105
  const fncCls: FunctionNode = this.classScope.get('construct') as FunctionNode;
@@ -140,7 +142,9 @@ export class ClassNode extends Node implements TreeNode {
140
142
  if (t.type === TokenType.L_BRACE) break;
141
143
  nameParts.push(t.value);
142
144
  }
143
- const selector = nameParts.join('').trim();
145
+ let selector = nameParts.join('').trim();
146
+ if (selector.startsWith('>'))
147
+ selector = `:scope ${selector}`;
144
148
  tokens.splice(0, nameParts.length);
145
149
  const block = Tree.processTokens(Tree.getNextStatementTokens(tokens, true, true));
146
150
  return new ClassNode(selector, block);
package/src/Attribute.ts CHANGED
@@ -24,7 +24,6 @@ export abstract class Attribute extends EventDispatcher {
24
24
  ) {
25
25
  super();
26
26
  this.configure();
27
- if (VisionHelper.window) VisionHelper.window['Attributes'].push(this);
28
27
  }
29
28
 
30
29
  public get origin(): Tag {
package/src/Component.ts CHANGED
@@ -21,6 +21,14 @@ export class Component extends HTMLElement {
21
21
  this.setAttribute('vsn-ref', '');
22
22
 
23
23
  this.shadow.appendChild(template.content.cloneNode(true));
24
+ this.shadow.querySelectorAll('slot').forEach(slot => {
25
+ slot.addEventListener('slotchange', async (e) => {
26
+ for (const child of slot.assignedNodes()) {
27
+ const t = await DOM.instance.getTagForElement(child as HTMLElement, true, true);
28
+ t?.slotted(slot);
29
+ }
30
+ });
31
+ });
24
32
  DOM.instance.buildFrom(this.shadow);
25
33
  }
26
34
  }
@@ -22,8 +22,9 @@ export abstract class DOMObject extends EventDispatcher {
22
22
  if (this.isSlot) {
23
23
  this.delegates.push(...(element as HTMLSlotElement).assignedNodes() as HTMLElement[]);
24
24
  }
25
- if (element.assignedSlot)
25
+ if (element.assignedSlot) {
26
26
  this.slot = element.assignedSlot;
27
+ }
27
28
  }
28
29
 
29
30
  public get isSlot(): boolean {
package/src/DOM.ts CHANGED
@@ -189,42 +189,41 @@ export class DOM extends EventDispatcher {
189
189
  }
190
190
  }
191
191
 
192
- async buildFrom(ele: any, isRoot: boolean = false) {
193
- // Assign parents to each tag
194
- const allElements: HTMLElement[] = [];
195
-
192
+ async buildFrom(ele: any, isRoot: boolean = false, forComponent: boolean = false) {
196
193
  if (isRoot) {
197
194
  document.body.setAttribute('vsn-root', '');
198
195
  document.ondragover = (e) => e.cancelable && e.preventDefault(); // Allow dragging over document
199
196
  }
200
197
 
201
- for (const tag of this.tags)
202
- allElements.push(tag.element);
203
-
204
198
  // Create tags for each html element with a v-attribute
205
199
  const newTags: Tag[] = [];
206
200
  const toBuild: HTMLElement[] = [];
207
- const toSkip: HTMLElement[] = [];
208
-
209
- if (ele && ele.querySelectorAll) {
210
- for (const element of (Array.from(ele.querySelectorAll(`*`)) as HTMLElement[])) { // Don't build items more than once
211
- if (!ElementHelper.hasVisionAttribute(element)) continue;
212
- if ((element.hasAttribute('vsn-template') && element.tagName === 'template') || toSkip.indexOf(element.parentElement) > -1) {
213
- toSkip.push(element);
214
- continue;
215
- }
216
- if (this.queued.indexOf(element) > -1) continue;
217
- this.queued.push(element);
218
- toBuild.push(element);
201
+
202
+ const checkElement = (e: HTMLElement) => {
203
+ if (ElementHelper.hasVisionAttribute(e)) {
204
+ if (
205
+ (!forComponent && e.hasAttribute('slot'))
206
+ ) return;
207
+ if (this.queued.indexOf(e) > -1) return;
208
+ this.queued.push(e);
209
+ toBuild.push(e);
210
+ }
211
+ }
212
+ const scanChildren = (e: HTMLElement) => {
213
+ for (const element of Array.from(e.children) as HTMLElement[]) {
214
+ checkElement(element);
215
+ if (element.tagName.toLowerCase() !== 'template')
216
+ scanChildren(element);
219
217
  }
220
218
  }
219
+ checkElement(ele);
220
+ scanChildren(ele);
221
221
 
222
222
  for (const element of toBuild) {
223
- if (allElements.indexOf(element) > -1) continue;
223
+ if (element[Tag.TaggedVariable]) continue;
224
224
  const tag: Tag = new Tag(element, this);
225
225
  this.tags.push(tag);
226
226
  newTags.push(tag);
227
- allElements.push(element as HTMLElement);
228
227
  }
229
228
 
230
229
  if (isRoot)
@@ -295,14 +294,14 @@ export class DOM extends EventDispatcher {
295
294
  return tags;
296
295
  }
297
296
 
298
- async getTagForElement(element: Element, create: boolean = false) {
297
+ async getTagForElement(element: Element, create: boolean = false, forComponent: boolean = false) {
299
298
  if (element[Tag.TaggedVariable])
300
299
  return element[Tag.TaggedVariable];
301
300
 
302
301
  if (element && create) {
303
302
  if (element instanceof HTMLElement)
304
303
  element.setAttribute('vsn-ref', '');
305
- await this.buildFrom(element.parentElement || element);
304
+ await this.buildFrom(element.parentElement || element, false, forComponent);
306
305
  return await this.getTagForElement(element, false);
307
306
  }
308
307
 
package/src/Tag.ts CHANGED
@@ -62,15 +62,18 @@ export class Tag extends DOMObject {
62
62
  this.onEventHandlers = {};
63
63
  this.analyzeElementAttributes();
64
64
  this._state = TagState.Instantiated;
65
- if (VisionHelper.window) {
66
- if (!VisionHelper.window['Tags']) {
67
- VisionHelper.window['Tags'] = [];
68
- VisionHelper.window['Attributes'] = [];
69
- }
70
- VisionHelper.window['Tags'].push(this);
65
+ if (this.hasAttribute('slot')) {
66
+ this.addEventHandler('slotted',[], (e) => {
67
+ console.log('slot change', e, this.element.assignedSlot);
68
+ })
71
69
  }
72
70
  }
73
71
 
72
+ public slotted(slot: HTMLSlotElement) {
73
+ this.slot = slot;
74
+ console.log('i am slotted', slot);
75
+ }
76
+
74
77
  protected onAttributeStateChange(event) {
75
78
  if (event.previouseState === AttributeState.Deferred) // @todo: what is this?
76
79
  this._nonDeferredAttributes.length = 0;
@@ -26,15 +26,15 @@ export class JSONAttribute extends Attribute {
26
26
  } else {
27
27
  json = unescape(this.getAttributeValue());
28
28
  }
29
- const property = this.getAttributeBinding();
30
29
  const data = JSON.parse(json);
30
+
31
31
  if (data && typeof data === 'object' && data.constructor === Object) {
32
32
  const newScope = new Scope(scope);
33
33
  newScope.wrap(data);
34
34
  scope.set(key, newScope);
35
+ } else {
36
+ scope.set(key, data);
35
37
  }
36
-
37
- scope.set(key, data);
38
38
  await super.extract();
39
39
  }
40
40
  }
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = '0.1.87';
1
+ export const VERSION = '0.1.88';
2
2
 
@@ -3,23 +3,23 @@ import {DOM} from "../../src/DOM";
3
3
  describe('JSONAttribute', () => {
4
4
  it("vsn-json should work with script/ld-json and an array", (done) => {
5
5
  document.body.innerHTML = `
6
- <script type="application/ld+json" vsn-json:test>
6
+ <script type="application/ld+json" vsn-json:t0>
7
7
  [1,2,3,"four"]
8
8
  </script>
9
9
  `;
10
10
  const dom = new DOM(document);
11
11
  dom.once('built', async () => {
12
- expect(dom.root.scope.get('test')[0]).toBe(1);
13
- expect(dom.root.scope.get('test')[1]).toBe(2);
14
- expect(dom.root.scope.get('test')[2]).toBe(3);
15
- expect(dom.root.scope.get('test')[3]).toBe("four");
12
+ expect(dom.root.scope.get('t0')[0]).toBe(1);
13
+ expect(dom.root.scope.get('t0')[1]).toBe(2);
14
+ expect(dom.root.scope.get('t0')[2]).toBe(3);
15
+ expect(dom.root.scope.get('t0')[3]).toBe("four");
16
16
  done();
17
17
  });
18
18
  });
19
19
 
20
20
  it("vsn-json should work with script/ld-json and an object", (done) => {
21
21
  document.body.innerHTML = `
22
- <script type="application/ld+json" vsn-json:test>
22
+ <script type="application/ld+json" vsn-json:t1>
23
23
  {
24
24
  "testing": [1,2,3,"four"],
25
25
  "test": ["one","two","three",4],
@@ -29,47 +29,49 @@ describe('JSONAttribute', () => {
29
29
  `;
30
30
  const dom = new DOM(document);
31
31
  dom.once('built', async () => {
32
- expect(dom.root.scope.get('test').get("testing")[0]).toBe(1);
33
- expect(dom.root.scope.get('test').get("testing")[1]).toBe(2);
34
- expect(dom.root.scope.get('test').get("testing")[2]).toBe(3);
35
- expect(dom.root.scope.get('test').get("testing")[3]).toBe("four");
36
- expect(dom.root.scope.get('test').get("test")[0]).toBe("one");
37
- expect(dom.root.scope.get('test').get("test")[1]).toBe("two");
38
- expect(dom.root.scope.get('test').get("test")[2]).toBe("three");
39
- expect(dom.root.scope.get('test').get("test")[3]).toBe(4);
40
- expect(dom.root.scope.get('test').get("val")).toBe(111);
32
+ expect(dom.root.scope.get('t1').get("testing")[0]).toBe(1);
33
+ expect(dom.root.scope.get('t1').get("testing")[1]).toBe(2);
34
+ expect(dom.root.scope.get('t1').get("testing")[2]).toBe(3);
35
+ expect(dom.root.scope.get('t1').get("testing")[3]).toBe("four");
36
+ expect(dom.root.scope.get('t1').get("test")[0]).toBe("one");
37
+ expect(dom.root.scope.get('t1').get("test")[1]).toBe("two");
38
+ expect(dom.root.scope.get('t1').get("test")[2]).toBe("three");
39
+ expect(dom.root.scope.get('t1').get("test")[3]).toBe(4);
40
+ expect(dom.root.scope.get('t1').get("val")).toBe(111);
41
41
  done();
42
42
  });
43
43
  });
44
44
 
45
45
  it("vsn-json should work with div and an array", (done) => {
46
46
  document.body.innerHTML = `
47
- <div vsn-json:test="[1,2,3,&quot;four&quot;]"></div>
47
+ <div vsn-json:t2="[1,2,3,&quot;four&quot;]"></div>
48
48
  `;
49
+
49
50
  const dom = new DOM(document);
50
51
  dom.once('built', async () => {
51
- expect(dom.root.scope.get('test')[0]).toBe(1);
52
- expect(dom.root.scope.get('test')[1]).toBe(2);
53
- expect(dom.root.scope.get('test')[2]).toBe(3);
54
- expect(dom.root.scope.get('test')[3]).toBe("four");
52
+ console.log('scope keys', dom.root.scope.keys);
53
+ expect(dom.root.scope.get('t2')[0]).toBe(1);
54
+ expect(dom.root.scope.get('t2')[1]).toBe(2);
55
+ expect(dom.root.scope.get('t2')[2]).toBe(3);
56
+ expect(dom.root.scope.get('t2')[3]).toBe("four");
55
57
  done();
56
58
  });
57
59
  });
58
60
 
59
61
  it("vsn-json should work with div and an object", (done) => {
60
62
  document.body.innerHTML = `
61
- <div vsn-json:test="{&quot;testing&quot;: [1,2,3,&quot;four&quot;],&quot;test&quot;: [&quot;one&quot;,&quot;two&quot;,&quot;three&quot;,4]}"></div>
63
+ <div vsn-json:t3="{&quot;testing&quot;: [1,2,3,&quot;four&quot;],&quot;test&quot;: [&quot;one&quot;,&quot;two&quot;,&quot;three&quot;,4]}"></div>
62
64
  `;
63
65
  const dom = new DOM(document);
64
66
  dom.once('built', async () => {
65
- expect(dom.root.scope.get('test').get("testing")[0]).toBe(1);
66
- expect(dom.root.scope.get('test').get("testing")[1]).toBe(2);
67
- expect(dom.root.scope.get('test').get("testing")[2]).toBe(3);
68
- expect(dom.root.scope.get('test').get("testing")[3]).toBe("four");
69
- expect(dom.root.scope.get('test').get("test")[0]).toBe("one");
70
- expect(dom.root.scope.get('test').get("test")[1]).toBe("two");
71
- expect(dom.root.scope.get('test').get("test")[2]).toBe("three");
72
- expect(dom.root.scope.get('test').get("test")[3]).toBe(4);
67
+ expect(dom.root.scope.get('t3').get("testing")[0]).toBe(1);
68
+ expect(dom.root.scope.get('t3').get("testing")[1]).toBe(2);
69
+ expect(dom.root.scope.get('t3').get("testing")[2]).toBe(3);
70
+ expect(dom.root.scope.get('t3').get("testing")[3]).toBe("four");
71
+ expect(dom.root.scope.get('t3').get("test")[0]).toBe("one");
72
+ expect(dom.root.scope.get('t3').get("test")[1]).toBe("two");
73
+ expect(dom.root.scope.get('t3').get("test")[2]).toBe("three");
74
+ expect(dom.root.scope.get('t3').get("test")[3]).toBe(4);
73
75
  done();
74
76
  });
75
77
  });