posthtml-component 1.0.0-RC.1

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.
@@ -0,0 +1,116 @@
1
+ 'use strict';
2
+
3
+ const {match} = require('posthtml/lib/api');
4
+ const {render} = require('posthtml-render');
5
+ const each = require('lodash/each');
6
+ const omit = require('lodash/omit');
7
+
8
+ /**
9
+ * Set filled slots
10
+ *
11
+ * @param {Object} currentNode PostHTML tree
12
+ * @param {Object} filledSlots
13
+ * @param {String} fill Fill tag name
14
+ * @param {String} slotSeparator Slot separator
15
+ * @return {void}
16
+ */
17
+ function setFilledSlots(currentNode, filledSlots, {fill, slotSeparator, propsSlot}) {
18
+ match.call(currentNode, {tag: fill}, fillNode => {
19
+ if (!fillNode.attrs) {
20
+ fillNode.attrs = {};
21
+ }
22
+
23
+ const name = fillNode.tag.split(slotSeparator)[1];
24
+
25
+ const props = omit(fillNode.attrs, ['append', 'prepend', 'aware']);
26
+
27
+ if (props) {
28
+ each(props, (value, key, attrs) => {
29
+ try {
30
+ attrs[key] = JSON.parse(value);
31
+ } catch {}
32
+ });
33
+ }
34
+
35
+ filledSlots[name] = {
36
+ filled: true,
37
+ rendered: false,
38
+ tag: fillNode.tag,
39
+ attrs: fillNode.attrs,
40
+ content: fillNode.content,
41
+ source: render(fillNode.content),
42
+ [propsSlot]: props
43
+ };
44
+
45
+ return fillNode;
46
+ });
47
+ }
48
+
49
+ /**
50
+ * Process <fill> tag
51
+ *
52
+ * @param {Object} tree PostHTML tree
53
+ * @param {Object} filledSlots Filled slots content
54
+ * @param {String} fill Fill tag name
55
+ * @param {String} slotSeparator Slot separator
56
+ * @return {void}
57
+ */
58
+ function processFillContent(tree, filledSlots, {fill, slotSeparator}) {
59
+ match.call(tree, {tag: fill}, fillNode => {
60
+ const name = fillNode.tag.split(slotSeparator)[1];
61
+
62
+ filledSlots[name].tag = fillNode.tag;
63
+ filledSlots[name].attrs = fillNode.attrs;
64
+ filledSlots[name].content = fillNode.content;
65
+ filledSlots[name].source = render(fillNode.content);
66
+ filledSlots[name].rendered = false;
67
+
68
+ fillNode.tag = false;
69
+ fillNode.content = null;
70
+
71
+ return fillNode;
72
+ });
73
+ }
74
+
75
+ /**
76
+ * Process <slot> tag
77
+ *
78
+ * @param {Object} tree PostHTML tree
79
+ * @param {Object} filledSlots Filled slots content
80
+ * @param {String} slot Slot tag name
81
+ * @param {String} slotSeparator Slot separator
82
+ * @return {void}
83
+ */
84
+ function processSlotContent(tree, filledSlots, {slot, slotSeparator}) {
85
+ match.call(tree, {tag: slot}, slotNode => {
86
+ const name = slotNode.tag.split(slotSeparator)[1];
87
+
88
+ slotNode.tag = false;
89
+
90
+ if (!filledSlots[name]) {
91
+ return slotNode;
92
+ }
93
+
94
+ if (filledSlots[name].rendered) {
95
+ slotNode.content = null;
96
+ } else if (slotNode.content && filledSlots[name].attrs && (typeof filledSlots[name].attrs.append !== 'undefined' || typeof filledSlots[name].attrs.prepend !== 'undefined')) {
97
+ slotNode.content = typeof filledSlots[name].attrs.append === 'undefined' ? filledSlots[name].content.concat(slotNode.content) : slotNode.content.concat(filledSlots[name].content);
98
+ } else {
99
+ slotNode.content = filledSlots[name].content;
100
+ }
101
+
102
+ // Set rendered to true so a slot can be output only once,
103
+ // when not present "aware" attribute
104
+ if (filledSlots[name] && (!filledSlots[name].attrs || typeof filledSlots[name].attrs.aware === 'undefined')) {
105
+ filledSlots[name].rendered = true;
106
+ }
107
+
108
+ return slotNode;
109
+ });
110
+ }
111
+
112
+ module.exports = {
113
+ setFilledSlots,
114
+ processFillContent,
115
+ processSlotContent
116
+ };
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+
3
+ const {match} = require('posthtml/lib/api');
4
+ const {render} = require('posthtml-render');
5
+
6
+ /**
7
+ * Process <push> tag
8
+ *
9
+ * @param {Object} tree PostHTML tree
10
+ * @param {Object} content Content pushed by stack name
11
+ * @param {String} push Push tag name
12
+ * @return {Object} tree
13
+ */
14
+ function processPushes(tree, content, push) {
15
+ match.call(tree, {tag: push}, pushNode => {
16
+ if (!pushNode.attrs || !pushNode.attrs.name) {
17
+ throw new Error(`[components] Push <${push}> tag must have an attribute "name".`);
18
+ }
19
+
20
+ if (!content[pushNode.attrs.name]) {
21
+ content[pushNode.attrs.name] = [];
22
+ }
23
+
24
+ const pushContent = render(pushNode.content);
25
+
26
+ // Review as rendered content is not anymore processable by others plugin
27
+ if (typeof pushNode.attrs.once === 'undefined' || !content[pushNode.attrs.name].includes(pushContent)) {
28
+ if (typeof pushNode.attrs.prepend === 'undefined') {
29
+ content[pushNode.attrs.name].push(pushContent);
30
+ } else {
31
+ content[pushNode.attrs.name].unshift(pushContent);
32
+ }
33
+ }
34
+
35
+ pushNode.tag = false;
36
+ pushNode.content = null;
37
+
38
+ return pushNode;
39
+ });
40
+
41
+ return tree;
42
+ }
43
+
44
+ /**
45
+ * Process <stack> tag
46
+ *
47
+ * @param {Object} tree PostHTML tree
48
+ * @param {Object} content Content pushed by stack name
49
+ * @param {String} stack Stack tag name
50
+ * @return {Object} tree
51
+ */
52
+ function processStacks(tree, content, stack) {
53
+ match.call(tree, {tag: stack}, stackNode => {
54
+ stackNode.tag = false;
55
+ stackNode.content = content[stackNode.attrs.name];
56
+ return stackNode;
57
+ });
58
+
59
+ return tree;
60
+ }
61
+
62
+ module.exports = {
63
+ processPushes,
64
+ processStacks
65
+ };