Skip to content

Commit f967aa3

Browse files
Release beta.16
1 parent 975eb25 commit f967aa3

19 files changed

+209
-35
lines changed

changelog.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 1.0.0-beta.16 (2022-11-06)
2+
3+
* Fix aware props propagation
4+
* Add utility `isEnabled` to check if a prop is either `<div myprop>` or `<div myprop="true">`
5+
16
## 1.0.0-beta.15 (2022-11-04)
27

38
* Fix aware props must be available only to nested components

docs-src/components/test/a.html

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script props>
2+
module.exports = {
3+
myprop: props.myprop || 'Default prop'
4+
}
5+
</script>
6+
7+
<div><yield></yield></div>

docs-src/components/test/b.html

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script props>
2+
module.exports = {
3+
myprop: props.myprop || 'Default prop'
4+
}
5+
</script>
6+
7+
<div>{{ myprop }}</div>

docs-src/components/test/layout.html

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script props>
2+
module.exports = {
3+
layoutprop: props.layoutprop || 'Default layoutprop'
4+
}
5+
</script>
6+
7+
<div>
8+
{{ layoutprop }}
9+
<yield></yield>
10+
</div>

docs-src/index.js

+4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ const md = './docs-src/md';
1616
const options = {};
1717

1818
readdirSync(src).forEach(file => {
19+
if (file !== 'test.html') {
20+
return;
21+
}
22+
1923
const html = readFileSync(path.resolve(`${src}${file}`), 'utf-8');
2024

2125
posthtml([

docs-src/md/changelog.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 1.0.0-beta.16 (2022-11-06)
2+
3+
* Fix aware props propagation
4+
* Add utility `isEnabled` to check if a prop is either `<div myprop>` or `<div myprop="true">`
5+
16
## 1.0.0-beta.15 (2022-11-04)
27

38
* Fix aware props must be available only to nested components

docs-src/pages/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ <h1 class="display-1 fw-bold mb-4">Build the web with PostHTML</h1>
1414
</div>
1515

1616
<p class="text-muted">
17-
Currently <strong>v1.0.0-beta.15</strong>
17+
Currently <strong>v1.0.0-beta.16</strong>
1818
<span class="px-1">·</span>
1919
<a href="#" class="link-secondary" data-bs-toggle="modal" data-bs-target="#modalWithComponents">Changelog</a>
2020
</p>

docs-src/pages/test.html

+22
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,28 @@ <h1 class="display-1 fw-bold mb-4">Playground</h1>
3737
</x-test.div2>
3838
</x-test.div1>
3939

40+
<x-test.a aware:myprop="I am aware prop">
41+
<x-test.b></x-test.b>
42+
<x-test.b></x-test.b>
43+
</x-test.a>
44+
45+
<x-test.a>
46+
<x-test.b></x-test.b>
47+
<x-test.b></x-test.b>
48+
</x-test.a>
49+
50+
<x-test.layout aware:layoutprop="Title">
51+
<x-test.a aware:myprop="I am aware prop">
52+
<x-test.b></x-test.b>
53+
<x-test.b></x-test.b>
54+
</x-test.a>
55+
56+
<x-test.a>
57+
<x-test.b></x-test.b>
58+
<x-test.b></x-test.b>
59+
</x-test.a>
60+
</x-test.layout>
61+
4062
<x-test
4163
aStringOverride="My override string changed"
4264
anObjectOverride='{ "third": "Third override item", "fourth": "Fourth override item" }'

docs/test.html

+34
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,25 @@ <h1 class="display-1 fw-bold mb-4">Playground</h1>
8585
</div>
8686
</div>
8787
</div>
88+
<div>
89+
<div>I am aware prop</div>
90+
<div>I am aware prop</div>
91+
</div>
92+
<div>
93+
<div>Default prop</div>
94+
<div>Default prop</div>
95+
</div>
96+
<div>
97+
Title
98+
<div>
99+
<div>I am aware prop</div>
100+
<div>I am aware prop</div>
101+
</div>
102+
<div>
103+
<div>Default prop</div>
104+
<div>Default prop</div>
105+
</div>
106+
</div>
88107
<div class="wrapper">
89108
<div class="demo my-demo" computed:acomputed="true" something="alocal">
90109
{"title":"PostHTML Components","aStringOverride":"My override string changed","anObjectOverride":{"third":"Third override item","fourth":"Fourth override item"},"computed:aComputed":true,"class":"my-demo","anObjectMerged":{"third":"Third merged item","fourth":"Fourth merged item","anObjectMerged1":{"third":"Third merged item (UPDATED?)","fourth1":"Fourth merged item"}},"post":{"title":"My post title","body":"My post body","comments":[{"id":1,"body":"My comment 1 new"},{"id":3,"body":"My comment 3"}]},"anArrayOfObjects":[{"id":1,"title":"My new title 1"},{"id":2,"title":"My new title 2","somethingnew":"New"}],"anArray":["first","third","fourth","ten"],"something":"alocal"}
@@ -259,6 +278,21 @@ <h5 class="modal-title" id="modalWithComponentsLabel">Changelog</h5>
259278
</div>
260279
<!-- /.modal-header -->
261280
<div class="modal-body">
281+
<h2 id="1.0.0-beta.16-(2022-11-06)" tabindex="-1">
282+
<a class="header-anchor" href="#1.0.0-beta.16-(2022-11-06)">#</a>
283+
1.0.0-beta.16 (2022-11-06)
284+
</h2>
285+
<ul>
286+
<li>Fix aware props propagation</li>
287+
<li>
288+
Add utility
289+
<code>isEnabled</code>
290+
to check if a prop is either
291+
<code>&lt;div myprop&gt;</code>
292+
or
293+
<code>&lt;div myprop=&quot;true&quot;&gt;</code>
294+
</li>
295+
</ul>
262296
<h2 id="1.0.0-beta.15-(2022-11-04)" tabindex="-1">
263297
<a class="header-anchor" href="#1.0.0-beta.15-(2022-11-04)">#</a>
264298
1.0.0-beta.15 (2022-11-04)

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "posthtml-component",
3-
"version": "1.0.0-beta.15",
3+
"version": "1.0.0-beta.16",
44
"description": "PostHTML Components Blade-like with slots, attributes as props and custom tag",
55
"license": "MIT",
66
"repository": "thewebartisan7/posthtml-components",

src/index.js

+50-23
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
const {readFileSync, existsSync} = require('fs');
44
const path = require('path');
55
const {parser} = require('posthtml-parser');
6-
const {match} = require('posthtml/lib/api');
6+
const {match, walk} = require('posthtml/lib/api');
77
const expressions = require('posthtml-expressions');
88
const findPathFromTag = require('./find-path');
99
const processProps = require('./process-props');
1010
const processAttributes = require('./process-attributes');
1111
const {processPushes, processStacks} = require('./process-stacks');
1212
const {setFilledSlots, processSlotContent, processFillContent} = require('./process-slots');
13+
const log = require('./log');
1314
const each = require('lodash/each');
1415
const defaults = require('lodash/defaults');
1516
const assignWith = require('lodash/assignWith');
@@ -24,14 +25,9 @@ const isBoolean = require('lodash/isBoolean');
2425
const isUndefined = require('lodash/isUndefined'); // value === undefined
2526
const isNull = require('lodash/isNull'); // value === null
2627
const isNil = require('lodash/isNil'); // value == null
27-
28-
// const {inspect} = require('util');
29-
// const debug = true;
30-
// const log = (object, what, method) => {
31-
// if (debug === true || method === debug) {
32-
// console.log(what, inspect(object, false, null, true));
33-
// }
34-
// };
28+
const uniqueId = require('lodash/uniqueId');
29+
const transform = require('lodash/transform');
30+
const assign = require('lodash/assign');
3531

3632
/* eslint-disable complexity */
3733
module.exports = (options = {}) => tree => {
@@ -71,7 +67,9 @@ module.exports = (options = {}) => tree => {
7167
isBoolean,
7268
isUndefined,
7369
isNull,
74-
isNil
70+
isNil,
71+
uniqueId,
72+
isEnabled: prop => prop === true || prop === ''
7573
};
7674

7775
// Merge customizer callback passed to lodash mergeWith
@@ -120,9 +118,12 @@ module.exports = (options = {}) => tree => {
120118
});
121119

122120
options.props = {...options.expressions.locals};
121+
options.aware = {};
123122

124123
const pushedContent = {};
125124

125+
log('Start of processing..', 'init', 'success');
126+
126127
return processStacks(
127128
processPushes(
128129
processTree(options)(
@@ -137,21 +138,27 @@ module.exports = (options = {}) => tree => {
137138
};
138139
/* eslint-enable complexity */
139140

141+
// Used for reset aware props
142+
let processCounter = 0;
143+
140144
/**
141145
* @param {Object} options Plugin options
142146
* @return {Object} PostHTML tree
143147
*/
144-
let processCounter = 0;
145148

146149
function processTree(options) {
147150
const filledSlots = {};
148151

149152
return function (tree) {
153+
log(`Processing tree number ${processCounter}..`, 'processTree');
154+
150155
if (options.plugins.length > 0) {
151156
tree = applyPluginsToTree(tree, options.plugins);
152157
}
153158

154159
match.call(tree, options.matcher, currentNode => {
160+
log(`Match found for tag "${currentNode.tag}"..`, 'processTree');
161+
155162
if (!currentNode.attrs) {
156163
currentNode.attrs = {};
157164
}
@@ -162,24 +169,21 @@ function processTree(options) {
162169
return currentNode;
163170
}
164171

165-
console.log(`${++processCounter}) Processing "${currentNode.tag}" component from "${componentPath}"`);
166-
167-
// log(currentNode, 'currentNode');
172+
log(`${++processCounter}) Processing "${currentNode.tag}" from "${componentPath}"`, 'processTree');
168173

169174
let nextNode = parser(readFileSync(componentPath, 'utf8'));
170175

171176
// Set filled slots
172177
setFilledSlots(currentNode, filledSlots, options);
173178

174-
// Reset options.aware when new nested start
175-
if (processCounter === 1) {
176-
options.aware = {};
177-
}
179+
const aware = transform(options.aware, (result, value) => {
180+
assign(result, value);
181+
}, {});
178182

179183
// Reset options.expressions.locals and keep aware locals
180-
options.expressions.locals = {...options.props, ...options.aware};
184+
options.expressions.locals = {...options.props, ...aware};
181185

182-
const {attributes, props} = processProps(currentNode, nextNode, filledSlots, options, componentPath);
186+
const {attributes, props} = processProps(currentNode, nextNode, filledSlots, options, componentPath, processCounter);
183187

184188
options.expressions.locals = attributes;
185189
options.expressions.locals.$slots = filledSlots;
@@ -208,14 +212,37 @@ function processTree(options) {
208212
currentNode.tag = false;
209213
currentNode.content = content;
210214

211-
processAttributes(currentNode, attributes, props, options);
215+
processAttributes(currentNode, attributes, props, options, aware);
216+
217+
// Remove attributes when value is 'null' or 'undefined'
218+
// so we can conditionally add an attribute by setting value to 'undefined' or 'null'.
219+
walk.call(currentNode, node => {
220+
if (node && node.attrs) {
221+
each(node.attrs, (value, key) => {
222+
if (['undefined', 'null'].includes(value)) {
223+
delete node.attrs[key];
224+
}
225+
});
226+
}
227+
228+
return node;
229+
});
230+
231+
log(`Done processing number ${processCounter}.`, 'processTree', 'success');
232+
233+
// Reset options.aware for current processCounter
234+
delete options.aware[processCounter];
212235

213-
// Reset counter
214-
processCounter = 0;
236+
// Decrement counter
237+
processCounter--;
215238

216239
return currentNode;
217240
});
218241

242+
if (processCounter === 0) {
243+
log('End of processing', 'processTree', 'success');
244+
}
245+
219246
return tree;
220247
};
221248
}

src/log.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
const {inspect} = require('util');
2+
3+
const debug = false;
4+
5+
// Colors
6+
const colors = {
7+
reset: '\u001B[0m',
8+
error: '\u001B[31m',
9+
success: '\u001B[32m',
10+
warning: '\u001B[33m',
11+
12+
errorHighlight: '\u001B[41m',
13+
successHighlight: '\u001B[42m',
14+
warningHighlight: '\u001B[43m',
15+
16+
highlighted: '\u001B[45m'
17+
};
18+
19+
module.exports = (message, method, level = 'reset', object = null) => {
20+
if (debug === true || method === debug) {
21+
if (object) {
22+
console.log(`[${colors.highlighted}x-components ${method}()${colors.reset}]`, colors[level] || 'reset', message, inspect(object, false, null, true), colors.reset);
23+
} else {
24+
console.log(`[${colors.highlighted}x-components ${method}()${colors.reset}]`, colors[level] || 'reset', message, colors.reset);
25+
}
26+
}
27+
};

src/process-attributes.js

+7-7
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ const isObject = require('lodash/isObject');
1919
* @param {Object} attributes
2020
* @param {Object} props
2121
* @param {Object} options
22+
* @param {Object} aware
2223
* @return {void}
2324
*/
24-
module.exports = (currentNode, attributes, props, options) => {
25+
module.exports = (currentNode, attributes, props, options, aware) => {
2526
let mainNode;
2627
match.call(currentNode, {attrs: {attributes: ''}}, node => {
2728
delete node.attrs.attributes;
@@ -42,7 +43,7 @@ module.exports = (currentNode, attributes, props, options) => {
4243

4344
const nodeAttrs = parseAttrs(mainNode.attrs, options.attrsParserRules);
4445

45-
const mainNodeAttributes = omit(attributes, union(keys(props), [options.attribute], keys(options.aware), keys(options.props), ['$slots']));
46+
const mainNodeAttributes = omit(attributes, union(keys(props), [options.attribute], keys(aware), keys(options.props), ['$slots']));
4647

4748
each(mainNodeAttributes, (value, key) => {
4849
if (['class', 'style'].includes(key)) {
@@ -62,12 +63,11 @@ module.exports = (currentNode, attributes, props, options) => {
6263
delete attributes[key];
6364
});
6465

65-
// Remove an attribute if value is 'null' or 'undefined'
66-
// so we can conditionally add an attribute
66+
// The plugin posthtml-attrs-parser compose() method expects a string,
67+
// but since we are JSON parsing, values like "-1" become number -1.
68+
// So below we convert non string values to string.
6769
each(nodeAttrs, (value, key) => {
68-
if (['undefined', 'null'].includes(value)) {
69-
delete nodeAttrs[key];
70-
} else if (key !== 'compose' && !isObject(nodeAttrs[key]) && !isString(nodeAttrs[key])) {
70+
if (key !== 'compose' && !isObject(nodeAttrs[key]) && !isString(nodeAttrs[key])) {
7171
nodeAttrs[key] = nodeAttrs[key].toString();
7272
}
7373
});

src/process-props.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ const attributeTypes = ['aware', 'merge'];
1616
* @param {Object} filledSlots - Filled slots
1717
* @param {Object} options - Plugin options
1818
* @param {string} componentPath - Component path
19+
* @param {number} processCounter
1920
* @return {Object} - Attribute props and script props
2021
*/
21-
module.exports = (currentNode, nextNode, filledSlots, options, componentPath) => {
22+
module.exports = (currentNode, nextNode, filledSlots, options, componentPath, processCounter) => {
2223
let attributes = {...currentNode.attrs};
2324

2425
const attributesByTypeName = {};
@@ -75,7 +76,7 @@ module.exports = (currentNode, nextNode, filledSlots, options, componentPath) =>
7576

7677
// Set aware attributes
7778
if (attributesByTypeName.aware.length > 0) {
78-
options.aware = pick(attributes, attributesByTypeName.aware);
79+
options.aware[processCounter] = pick(attributes, attributesByTypeName.aware);
7980
}
8081

8182
return {attributes, props};

0 commit comments

Comments
 (0)