@domql/element 3.4.5 → 3.4.9

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 (47) hide show
  1. package/event/__tests__/applyAnimationFrame.test.js +114 -0
  2. package/event/__tests__/applyEvent.test.js +159 -0
  3. package/event/__tests__/applyEventUpdate.test.js +198 -0
  4. package/event/__tests__/applyEventsOnNode.test.js +216 -0
  5. package/event/__tests__/canRenderTag.test.js +50 -0
  6. package/event/__tests__/index.test.js +39 -0
  7. package/event/__tests__/initAnimationFrame.test.js +156 -0
  8. package/event/__tests__/registerFrameListener.test.js +97 -0
  9. package/event/__tests__/store.test.js +93 -0
  10. package/event/__tests__/triggerEventOn.test.js +195 -0
  11. package/event/__tests__/triggerEventOnUpdate.test.js +207 -0
  12. package/event/animationFrame.js +92 -0
  13. package/event/can.js +8 -0
  14. package/event/index.js +5 -0
  15. package/event/on.js +71 -0
  16. package/event/store.js +6 -0
  17. package/methods/set.js +73 -0
  18. package/methods/v2.js +83 -0
  19. package/mixins/attr.js +32 -0
  20. package/mixins/classList.js +62 -0
  21. package/mixins/content.js +65 -0
  22. package/mixins/data.js +26 -0
  23. package/mixins/html.js +19 -0
  24. package/mixins/index.js +23 -0
  25. package/mixins/registry.js +46 -0
  26. package/mixins/scope.js +23 -0
  27. package/mixins/state.js +18 -0
  28. package/mixins/style.js +25 -0
  29. package/mixins/text.js +31 -0
  30. package/package.json +13 -8
  31. package/render/__tests__/appendNode.test.js +53 -0
  32. package/render/__tests__/assignNode.test.js +151 -0
  33. package/render/__tests__/cacheNode.test.js +168 -0
  34. package/render/__tests__/createHTMLNode.test.js +118 -0
  35. package/render/__tests__/createNode.test.js +9 -0
  36. package/render/__tests__/detectTag.test.js +99 -0
  37. package/render/__tests__/index.test.js +56 -0
  38. package/render/__tests__/insertNodeAfter.test.js +111 -0
  39. package/render/__tests__/insertNodeBefore.test.js +65 -0
  40. package/render/append.js +61 -0
  41. package/render/cache.js +68 -0
  42. package/render/create.js +3 -0
  43. package/render/index.js +5 -0
  44. package/utils/applyParam.js +33 -0
  45. package/utils/extendUtils.js +135 -0
  46. package/utils/index.js +4 -0
  47. package/utils/propEvents.js +36 -0
@@ -0,0 +1,168 @@
1
+ import { jest } from '@jest/globals'
2
+ import { cacheNode } from '../cache'
3
+
4
+ describe('cacheNode', () => {
5
+ // Setup mock window and document for each test
6
+ let mockNode
7
+ let mockTextNode
8
+ let mockFragmentNode
9
+ let mockSvgNode
10
+
11
+ beforeEach(() => {
12
+ mockNode = {
13
+ cloneNode: jest.fn().mockReturnThis()
14
+ }
15
+ mockTextNode = {
16
+ cloneNode: jest.fn().mockReturnThis(),
17
+ nodeValue: null
18
+ }
19
+ mockFragmentNode = {
20
+ cloneNode: jest.fn().mockReturnThis()
21
+ }
22
+ mockSvgNode = {
23
+ cloneNode: jest.fn().mockReturnThis()
24
+ }
25
+
26
+ global.window = {
27
+ nodeCaches: {}
28
+ }
29
+ global.document = {
30
+ createElement: jest.fn().mockReturnValue(mockNode),
31
+ createTextNode: jest.fn().mockReturnValue(mockTextNode),
32
+ createDocumentFragment: jest.fn().mockReturnValue(mockFragmentNode),
33
+ createElementNS: jest.fn().mockReturnValue(mockSvgNode)
34
+ }
35
+ })
36
+
37
+ test('should return cached node for div element', () => {
38
+ const element = {
39
+ tag: 'div',
40
+ context: {
41
+ window,
42
+ document
43
+ }
44
+ }
45
+ const result = cacheNode(element)
46
+ expect(result).toBeTruthy()
47
+ })
48
+
49
+ test('should return text node for string element', () => {
50
+ const element = {
51
+ tag: 'string',
52
+ text: 'Hello World',
53
+ context: {
54
+ window,
55
+ document
56
+ }
57
+ }
58
+ const result = cacheNode(element)
59
+ expect(result).toBeTruthy()
60
+ })
61
+
62
+ test('should return fragment node', () => {
63
+ const element = {
64
+ tag: 'fragment',
65
+ context: {
66
+ window,
67
+ document
68
+ }
69
+ }
70
+ const result = cacheNode(element)
71
+ expect(result).toBeTruthy()
72
+ })
73
+
74
+ test('should return svg node', () => {
75
+ const element = {
76
+ tag: 'svg',
77
+ context: {
78
+ window,
79
+ document
80
+ }
81
+ }
82
+ const result = cacheNode(element)
83
+ expect(result).toBeTruthy()
84
+ })
85
+
86
+ test('should return path node', () => {
87
+ const element = {
88
+ tag: 'path',
89
+ context: {
90
+ window,
91
+ document
92
+ }
93
+ }
94
+ const result = cacheNode(element)
95
+ expect(result).toBeTruthy()
96
+ })
97
+
98
+ test('should reuse cached node for same tag', () => {
99
+ const element = {
100
+ tag: 'span',
101
+ context: {
102
+ window,
103
+ document
104
+ }
105
+ }
106
+ const firstResult = cacheNode(element)
107
+ const secondResult = cacheNode(element)
108
+ expect(firstResult).toBeTruthy()
109
+ expect(secondResult).toBeTruthy()
110
+ })
111
+
112
+ test('should set nodeValue for string elements', () => {
113
+ const element = {
114
+ tag: 'string',
115
+ text: 'Test Text',
116
+ context: {
117
+ window,
118
+ document
119
+ }
120
+ }
121
+ const result = cacheNode(element)
122
+ expect(result).toBeTruthy()
123
+ })
124
+
125
+ test('should use window from context if provided', () => {
126
+ const customWindow = { nodeCaches: {} }
127
+ const element = {
128
+ tag: 'div',
129
+ context: {
130
+ window: customWindow,
131
+ document
132
+ }
133
+ }
134
+ const result = cacheNode(element)
135
+ expect(result).toBeTruthy()
136
+ })
137
+
138
+ test('should use document from context if provided', () => {
139
+ const customDocument = {
140
+ createElement: jest.fn().mockReturnValue(mockNode),
141
+ createTextNode: jest.fn().mockReturnValue(mockTextNode),
142
+ createDocumentFragment: jest.fn().mockReturnValue(mockFragmentNode),
143
+ createElementNS: jest.fn().mockReturnValue(mockSvgNode)
144
+ }
145
+ const element = {
146
+ tag: 'div',
147
+ context: {
148
+ window,
149
+ document: customDocument
150
+ }
151
+ }
152
+ const result = cacheNode(element)
153
+ expect(result).toBeTruthy()
154
+ })
155
+
156
+ test('should initialize nodeCaches if not present', () => {
157
+ global.window = {}
158
+ const element = {
159
+ tag: 'div',
160
+ context: {
161
+ window,
162
+ document
163
+ }
164
+ }
165
+ const result = cacheNode(element)
166
+ expect(result).toBeTruthy()
167
+ })
168
+ })
@@ -0,0 +1,118 @@
1
+ import { createHTMLNode } from '../cache'
2
+
3
+ describe('createHTMLNode', () => {
4
+ let element
5
+ let mockDocument
6
+ let mockDocumentFragment
7
+ let mockTextNode
8
+ let mockSvgElement
9
+ let mockDivElement
10
+
11
+ beforeEach(() => {
12
+ // Setup mock document
13
+ mockTextNode = document.createTextNode('')
14
+ mockDocumentFragment = document.createDocumentFragment()
15
+ mockSvgElement = document.createElementNS(
16
+ 'http://www.w3.org/2000/svg',
17
+ 'svg'
18
+ )
19
+ mockDivElement = document.createElement('div')
20
+
21
+ mockDocument = {
22
+ createTextNode: () => mockTextNode,
23
+ createDocumentFragment: () => mockDocumentFragment,
24
+ createElementNS: () => mockSvgElement,
25
+ createElement: () => mockDivElement
26
+ }
27
+
28
+ // Reset element before each test
29
+ element = {
30
+ context: {
31
+ document: mockDocument
32
+ }
33
+ }
34
+ })
35
+
36
+ test('should create text node when tag is string', () => {
37
+ element.tag = 'string'
38
+ element.text = 'Hello World'
39
+
40
+ const result = createHTMLNode(element)
41
+
42
+ expect(result.nodeType).toBe(Node.TEXT_NODE)
43
+ expect(result.textContent).toBe('')
44
+ })
45
+
46
+ test('should create document fragment when tag is fragment', () => {
47
+ element.tag = 'fragment'
48
+
49
+ const result = createHTMLNode(element)
50
+
51
+ expect(result.nodeType).toBe(Node.DOCUMENT_FRAGMENT_NODE)
52
+ })
53
+
54
+ test('should create SVG element when tag is svg', () => {
55
+ element.tag = 'svg'
56
+
57
+ const result = createHTMLNode(element)
58
+
59
+ expect(result.nodeType).toBe(Node.ELEMENT_NODE)
60
+ expect(result.namespaceURI).toBe('http://www.w3.org/2000/svg')
61
+ expect(result.tagName.toLowerCase()).toBe('svg')
62
+ })
63
+
64
+ test('should create SVG path element when tag is path', () => {
65
+ element.tag = 'svg'
66
+
67
+ const result = createHTMLNode(element)
68
+
69
+ expect(result.nodeType).toBe(Node.ELEMENT_NODE)
70
+ expect(result.namespaceURI).toBe('http://www.w3.org/2000/svg')
71
+ expect(result.tagName.toLowerCase()).toBe('svg')
72
+ })
73
+
74
+ test('should create regular HTML element for standard HTML tags', () => {
75
+ element.tag = 'div'
76
+
77
+ const result = createHTMLNode(element)
78
+
79
+ expect(result.nodeType).toBe(Node.ELEMENT_NODE)
80
+ expect(result.tagName.toLowerCase()).toBe('div')
81
+ })
82
+
83
+ test('should create div element when no tag is provided', () => {
84
+ delete element.tag
85
+
86
+ const result = createHTMLNode(element)
87
+
88
+ expect(result.nodeType).toBe(Node.ELEMENT_NODE)
89
+ expect(result.tagName.toLowerCase()).toBe('div')
90
+ })
91
+
92
+ test('should use document from context if provided', () => {
93
+ const customDoc = {
94
+ createElement: () => {
95
+ const el = document.createElement('custom')
96
+ el.setAttribute('from-custom-doc', 'true')
97
+ return el
98
+ }
99
+ }
100
+
101
+ element.context.document = customDoc
102
+ element.tag = 'div'
103
+
104
+ const result = createHTMLNode(element)
105
+
106
+ expect(result.getAttribute('from-custom-doc')).toBe('true')
107
+ })
108
+
109
+ test('should fallback to global document if context.document is not provided', () => {
110
+ delete element.context.document
111
+ element.tag = 'div'
112
+
113
+ const result = createHTMLNode(element)
114
+
115
+ expect(result.nodeType).toBe(Node.ELEMENT_NODE)
116
+ expect(result.tagName.toLowerCase()).toBe('div')
117
+ })
118
+ })
@@ -0,0 +1,9 @@
1
+ import { createNode } from '../create'
2
+
3
+ describe('createNode', () => {
4
+ test('should return a value when element is provided', () => {
5
+ const element = {}
6
+ const result = createNode(element)
7
+ expect(result).toBe(undefined)
8
+ })
9
+ })
@@ -0,0 +1,99 @@
1
+ import { detectTag } from '../cache'
2
+
3
+ describe('detectTag', () => {
4
+ test('should return tag from props.tag if it is a valid HTML tag', () => {
5
+ const element = {
6
+ tag: 'something',
7
+ key: 'key',
8
+ props: {
9
+ tag: 'div'
10
+ }
11
+ }
12
+ expect(detectTag(element)).toBe('div')
13
+ })
14
+
15
+ test('should return tag if it is a valid HTML tag string', () => {
16
+ const element = {
17
+ tag: 'span',
18
+ key: 'key',
19
+ props: {}
20
+ }
21
+ expect(detectTag(element)).toBe('span')
22
+ })
23
+
24
+ test('should return key as tag if tag is true', () => {
25
+ const element = {
26
+ tag: true,
27
+ key: 'div',
28
+ props: {}
29
+ }
30
+ expect(detectTag(element)).toBe('div')
31
+ })
32
+
33
+ test('should return div as default when no valid tag is found', () => {
34
+ const element = {
35
+ tag: 'invalid',
36
+ key: 'invalid',
37
+ props: {}
38
+ }
39
+ expect(detectTag(element)).toBe('div')
40
+ })
41
+
42
+ test('should handle function as tag', () => {
43
+ const element = {
44
+ tag: () => 'section',
45
+ key: 'key',
46
+ props: {}
47
+ }
48
+ expect(detectTag(element)).toBe('section')
49
+ })
50
+
51
+ test('should parse key with dots and return valid HTML tag', () => {
52
+ const element = {
53
+ tag: null,
54
+ key: 'span.className',
55
+ props: {}
56
+ }
57
+ expect(detectTag(element)).toBe('span')
58
+ })
59
+
60
+ test('should parse key with underscore and return valid HTML tag', () => {
61
+ const element = {
62
+ tag: null,
63
+ key: 'div_identifier',
64
+ props: {}
65
+ }
66
+ expect(detectTag(element)).toBe('div')
67
+ })
68
+
69
+ test('should handle null props', () => {
70
+ const element = {
71
+ tag: 'p',
72
+ key: 'key',
73
+ props: null
74
+ }
75
+ expect(detectTag(element)).toBe('p')
76
+ })
77
+
78
+ test('should handle props.tag that is not a valid HTML tag', () => {
79
+ const element = {
80
+ tag: 'div',
81
+ key: 'key',
82
+ props: {
83
+ tag: 'invalid-tag'
84
+ }
85
+ }
86
+ expect(detectTag(element)).toBe('div')
87
+ })
88
+
89
+ test('should handle complex nested case', () => {
90
+ const element = {
91
+ tag: null,
92
+ key: 'invalid.something_else',
93
+ props: {
94
+ tag: 'article'
95
+ }
96
+ }
97
+ expect(detectTag(element)).toBe('article')
98
+ })
99
+ })
@@ -0,0 +1,56 @@
1
+ import * as moduleExports from '../index'
2
+ import * as createExports from '../create'
3
+ import * as cacheExports from '../cache'
4
+ import * as appendExports from '../append'
5
+
6
+ describe('Module exports', () => {
7
+ test('should export all items from create.js', () => {
8
+ Object.keys(createExports).forEach(key => {
9
+ expect(moduleExports[key]).toBeDefined()
10
+ })
11
+ })
12
+
13
+ test('should export all items from cache.js', () => {
14
+ Object.keys(cacheExports).forEach(key => {
15
+ expect(moduleExports[key]).toBeDefined()
16
+ })
17
+ })
18
+
19
+ test('should export all items from append.js', () => {
20
+ Object.keys(appendExports).forEach(key => {
21
+ expect(moduleExports[key]).toBeDefined()
22
+ })
23
+ })
24
+
25
+ test('should have no duplicate exports', () => {
26
+ const allExportKeys = [
27
+ ...Object.keys(createExports),
28
+ ...Object.keys(cacheExports),
29
+ ...Object.keys(appendExports)
30
+ ]
31
+ const uniqueKeys = new Set(allExportKeys)
32
+ expect(allExportKeys.length).toBe(uniqueKeys.size)
33
+ })
34
+
35
+ test('should export same values as original modules', () => {
36
+ Object.entries(createExports).forEach(([key, value]) => {
37
+ expect(moduleExports[key]).toBe(value)
38
+ })
39
+
40
+ Object.entries(cacheExports).forEach(([key, value]) => {
41
+ expect(moduleExports[key]).toBe(value)
42
+ })
43
+
44
+ Object.entries(appendExports).forEach(([key, value]) => {
45
+ expect(moduleExports[key]).toBe(value)
46
+ })
47
+ })
48
+
49
+ test('should have all exports defined', () => {
50
+ const moduleExportKeys = Object.keys(moduleExports)
51
+ expect(moduleExportKeys.length).toBeGreaterThan(0)
52
+ moduleExportKeys.forEach(key => {
53
+ expect(moduleExports[key]).toBeDefined()
54
+ })
55
+ })
56
+ })
@@ -0,0 +1,111 @@
1
+ import { insertNodeAfter } from '../append'
2
+ import { jest } from '@jest/globals'
3
+
4
+ describe('insertNodeAfter', () => {
5
+ let parentNode
6
+ let siblingNode
7
+ let newNode
8
+
9
+ beforeEach(() => {
10
+ // Setup fresh DOM elements before each test
11
+ parentNode = document.createElement('div')
12
+ siblingNode = document.createElement('span')
13
+ newNode = document.createElement('p')
14
+
15
+ // Add sibling to parent for initial setup
16
+ parentNode.appendChild(siblingNode)
17
+ })
18
+
19
+ test('should throw error when node is null', () => {
20
+ expect(() => {
21
+ insertNodeAfter(null, siblingNode, parentNode)
22
+ }).toThrow('Node is required')
23
+
24
+ // Verify DOM wasn't modified
25
+ expect(parentNode.children).toHaveLength(1)
26
+ expect(parentNode.firstChild).toBe(siblingNode)
27
+ })
28
+
29
+ test('should insert node after sibling when there is a next sibling', () => {
30
+ // Arrange
31
+ const nextSibling = document.createElement('div')
32
+ parentNode.appendChild(nextSibling)
33
+
34
+ // Act
35
+ insertNodeAfter(newNode, siblingNode, parentNode)
36
+
37
+ // Assert
38
+ expect(parentNode.children).toHaveLength(3)
39
+ expect(siblingNode.nextSibling).toBe(newNode)
40
+ expect(newNode.nextSibling).toBe(nextSibling)
41
+ expect(newNode.previousSibling).toBe(siblingNode)
42
+ })
43
+
44
+ test('should insert node after sibling using insertAdjacentElement', () => {
45
+ // Mock insertAdjacentElement
46
+ const insertAdjacentElementMock = jest.fn()
47
+ siblingNode.insertAdjacentElement = insertAdjacentElementMock
48
+
49
+ // Act
50
+ insertNodeAfter(newNode, siblingNode, parentNode)
51
+
52
+ // Assert
53
+ expect(insertAdjacentElementMock).toHaveBeenCalledWith('afterend', newNode)
54
+ })
55
+
56
+ test('should insert node after sibling when no next sibling exists', () => {
57
+ // Act
58
+ insertNodeAfter(newNode, siblingNode, parentNode)
59
+
60
+ // Assert
61
+ expect(parentNode.children).toHaveLength(2)
62
+ expect(siblingNode.nextSibling).toBe(newNode)
63
+ expect(newNode.previousSibling).toBe(siblingNode)
64
+ expect(newNode.nextSibling).toBeNull()
65
+ })
66
+
67
+ test('should insert node after sibling using implicit parent', () => {
68
+ // Act
69
+ insertNodeAfter(newNode, siblingNode)
70
+
71
+ // Assert
72
+ expect(parentNode.children).toHaveLength(2)
73
+ expect(siblingNode.nextSibling).toBe(newNode)
74
+ expect(newNode.previousSibling).toBe(siblingNode)
75
+ })
76
+
77
+ test('should handle null sibling', () => {
78
+ // Act & Assert
79
+ expect(() => {
80
+ insertNodeAfter(newNode, null, parentNode)
81
+ }).not.toThrow()
82
+
83
+ // Verify no changes were made to the parent
84
+ expect(parentNode.children).toHaveLength(2)
85
+ })
86
+
87
+ test('should handle case when parent and sibling parent are both null', () => {
88
+ const standaloneNode = document.createElement('div')
89
+
90
+ // Act & Assert
91
+ expect(() => {
92
+ insertNodeAfter(newNode, standaloneNode, null)
93
+ }).not.toThrow()
94
+
95
+ expect(standaloneNode.nextSibling).toBeNull()
96
+ expect(standaloneNode.parentNode).toBeNull()
97
+ })
98
+
99
+ test('should handle sibling without insertAdjacentElement', () => {
100
+ // Create a minimal sibling without insertAdjacentElement
101
+ const customSibling = document.createElement('div')
102
+ delete customSibling.insertAdjacentElement
103
+
104
+ // Act
105
+ insertNodeAfter(newNode, customSibling, parentNode)
106
+
107
+ // Assert
108
+ expect(parentNode.children).toHaveLength(1)
109
+ expect(customSibling.nextSibling).toBe(null)
110
+ })
111
+ })
@@ -0,0 +1,65 @@
1
+ import { insertNodeBefore } from '../append'
2
+
3
+ describe('insertNodeBefore', () => {
4
+ let parentNode
5
+ let siblingNode
6
+ let newNode
7
+
8
+ beforeEach(() => {
9
+ // Setup fresh DOM elements before each test
10
+ parentNode = document.createElement('div')
11
+ siblingNode = document.createElement('span')
12
+ newNode = document.createElement('p')
13
+
14
+ // Add sibling to parent for initial setup
15
+ parentNode.appendChild(siblingNode)
16
+ })
17
+
18
+ test('should insert node before sibling with explicit parent', () => {
19
+ insertNodeBefore(newNode, siblingNode, parentNode)
20
+
21
+ expect(parentNode.children).toHaveLength(2)
22
+ expect(parentNode.firstChild).toBe(newNode)
23
+ expect(newNode.nextSibling).toBe(siblingNode)
24
+ })
25
+
26
+ test('should insert node before sibling using implicit parent', () => {
27
+ // Not passing parent parameter, using sibling's parent
28
+ insertNodeBefore(newNode, siblingNode)
29
+
30
+ expect(parentNode.children).toHaveLength(2)
31
+ expect(parentNode.firstChild).toBe(newNode)
32
+ expect(newNode.nextSibling).toBe(siblingNode)
33
+ })
34
+
35
+ test('should handle case when parent is null', () => {
36
+ const standaloneNode = document.createElement('div')
37
+ // Passing null as parent
38
+ insertNodeBefore(newNode, standaloneNode, null)
39
+
40
+ expect(standaloneNode.previousSibling).toBeNull()
41
+ expect(standaloneNode.parentNode).toBeNull()
42
+ })
43
+
44
+ test('should handle case when sibling has no parent', () => {
45
+ const standaloneNode = document.createElement('div')
46
+ insertNodeBefore(newNode, standaloneNode)
47
+
48
+ expect(standaloneNode.previousSibling).toBeNull()
49
+ expect(standaloneNode.parentNode).toBeNull()
50
+ })
51
+
52
+ test('should throw error when node is null', () => {
53
+ // Arrange
54
+ const errorMessage = 'Node is required'
55
+
56
+ // Act & Assert
57
+ expect(() => {
58
+ insertNodeBefore(null, siblingNode, parentNode)
59
+ }).toThrow(errorMessage)
60
+
61
+ // Verify the DOM wasn't modified
62
+ expect(parentNode.children).toHaveLength(1)
63
+ expect(parentNode.firstChild).toBe(siblingNode)
64
+ })
65
+ })
@@ -0,0 +1,61 @@
1
+ 'use strict'
2
+
3
+ /**
4
+ * Receives child and parent nodes as parametes
5
+ * and assigns them into real DOM tree
6
+ */
7
+ export const appendNode = (node, parentNode) => {
8
+ try {
9
+ parentNode.appendChild(node)
10
+ return node
11
+ } catch (e) {
12
+ console.error('Does not support to append', parentNode, node)
13
+ }
14
+ }
15
+
16
+ //q23
17
+ export const insertNodeAfter = (node, siblingNode, parentNode) => {
18
+ if (!node) {
19
+ throw new Error('Node is required')
20
+ }
21
+ const parent = parentNode || siblingNode?.parentNode
22
+ if (siblingNode?.nextSibling) {
23
+ parent?.insertBefore(node, siblingNode.nextSibling)
24
+ } else if (siblingNode?.insertAdjacentElement) {
25
+ siblingNode.insertAdjacentElement('afterend', node)
26
+ } else {
27
+ parent?.insertBefore(node, siblingNode)
28
+ }
29
+ }
30
+
31
+ export const insertNodeBefore = (node, siblingNode, parentNode) => {
32
+ if (!node) {
33
+ throw new Error('Node is required')
34
+ }
35
+ const parent = parentNode || siblingNode.parentNode
36
+ parent?.insertBefore(node, siblingNode)
37
+ }
38
+
39
+ /**
40
+ * Receives elements and assigns the first
41
+ * parameter as a child of the second one
42
+ */
43
+ export const assignNode = (element, parent, key, attachOptions) => {
44
+ if (!element) {
45
+ throw new Error('Element is required')
46
+ }
47
+ if (!parent) {
48
+ throw new Error('Parent is required')
49
+ }
50
+ parent[key || element.key] = element
51
+ if (element.tag !== 'shadow') {
52
+ if (attachOptions && attachOptions.position) {
53
+ ;(attachOptions.position === 'before'
54
+ ? insertNodeBefore
55
+ : insertNodeAfter)(element.node, attachOptions.node || parent.node)
56
+ } else {
57
+ appendNode(element.node, parent.node, element)
58
+ }
59
+ }
60
+ return element
61
+ }