Skip to content

Commit

Permalink
Release beta.16
Browse files Browse the repository at this point in the history
  • Loading branch information
thewebartisan7 committed Nov 6, 2022
1 parent 975eb25 commit f967aa3
Show file tree
Hide file tree
Showing 19 changed files with 209 additions and 35 deletions.
5 changes: 5 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 1.0.0-beta.16 (2022-11-06)

* Fix aware props propagation
* Add utility `isEnabled` to check if a prop is either `<div myprop>` or `<div myprop="true">`

## 1.0.0-beta.15 (2022-11-04)

* Fix aware props must be available only to nested components
Expand Down
7 changes: 7 additions & 0 deletions docs-src/components/test/a.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script props>
module.exports = {
myprop: props.myprop || 'Default prop'
}
</script>

<div><yield></yield></div>
7 changes: 7 additions & 0 deletions docs-src/components/test/b.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<script props>
module.exports = {
myprop: props.myprop || 'Default prop'
}
</script>

<div>{{ myprop }}</div>
10 changes: 10 additions & 0 deletions docs-src/components/test/layout.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<script props>
module.exports = {
layoutprop: props.layoutprop || 'Default layoutprop'
}
</script>

<div>
{{ layoutprop }}
<yield></yield>
</div>
4 changes: 4 additions & 0 deletions docs-src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ const md = './docs-src/md';
const options = {};

readdirSync(src).forEach(file => {
if (file !== 'test.html') {
return;
}

const html = readFileSync(path.resolve(`${src}${file}`), 'utf-8');

posthtml([
Expand Down
5 changes: 5 additions & 0 deletions docs-src/md/changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 1.0.0-beta.16 (2022-11-06)

* Fix aware props propagation
* Add utility `isEnabled` to check if a prop is either `<div myprop>` or `<div myprop="true">`

## 1.0.0-beta.15 (2022-11-04)

* Fix aware props must be available only to nested components
Expand Down
2 changes: 1 addition & 1 deletion docs-src/pages/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ <h1 class="display-1 fw-bold mb-4">Build the web with PostHTML</h1>
</div>

<p class="text-muted">
Currently <strong>v1.0.0-beta.15</strong>
Currently <strong>v1.0.0-beta.16</strong>
<span class="px-1">·</span>
<a href="#" class="link-secondary" data-bs-toggle="modal" data-bs-target="#modalWithComponents">Changelog</a>
</p>
Expand Down
22 changes: 22 additions & 0 deletions docs-src/pages/test.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,28 @@ <h1 class="display-1 fw-bold mb-4">Playground</h1>
</x-test.div2>
</x-test.div1>

<x-test.a aware:myprop="I am aware prop">
<x-test.b></x-test.b>
<x-test.b></x-test.b>
</x-test.a>

<x-test.a>
<x-test.b></x-test.b>
<x-test.b></x-test.b>
</x-test.a>

<x-test.layout aware:layoutprop="Title">
<x-test.a aware:myprop="I am aware prop">
<x-test.b></x-test.b>
<x-test.b></x-test.b>
</x-test.a>

<x-test.a>
<x-test.b></x-test.b>
<x-test.b></x-test.b>
</x-test.a>
</x-test.layout>

<x-test
aStringOverride="My override string changed"
anObjectOverride='{ "third": "Third override item", "fourth": "Fourth override item" }'
Expand Down
34 changes: 34 additions & 0 deletions docs/test.html
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,25 @@ <h1 class="display-1 fw-bold mb-4">Playground</h1>
</div>
</div>
</div>
<div>
<div>I am aware prop</div>
<div>I am aware prop</div>
</div>
<div>
<div>Default prop</div>
<div>Default prop</div>
</div>
<div>
Title
<div>
<div>I am aware prop</div>
<div>I am aware prop</div>
</div>
<div>
<div>Default prop</div>
<div>Default prop</div>
</div>
</div>
<div class="wrapper">
<div class="demo my-demo" computed:acomputed="true" something="alocal">
{"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"}
Expand Down Expand Up @@ -259,6 +278,21 @@ <h5 class="modal-title" id="modalWithComponentsLabel">Changelog</h5>
</div>
<!-- /.modal-header -->
<div class="modal-body">
<h2 id="1.0.0-beta.16-(2022-11-06)" tabindex="-1">
<a class="header-anchor" href="#1.0.0-beta.16-(2022-11-06)">#</a>
1.0.0-beta.16 (2022-11-06)
</h2>
<ul>
<li>Fix aware props propagation</li>
<li>
Add utility
<code>isEnabled</code>
to check if a prop is either
<code>&lt;div myprop&gt;</code>
or
<code>&lt;div myprop=&quot;true&quot;&gt;</code>
</li>
</ul>
<h2 id="1.0.0-beta.15-(2022-11-04)" tabindex="-1">
<a class="header-anchor" href="#1.0.0-beta.15-(2022-11-04)">#</a>
1.0.0-beta.15 (2022-11-04)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "posthtml-component",
"version": "1.0.0-beta.15",
"version": "1.0.0-beta.16",
"description": "PostHTML Components Blade-like with slots, attributes as props and custom tag",
"license": "MIT",
"repository": "thewebartisan7/posthtml-components",
Expand Down
73 changes: 50 additions & 23 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
const {readFileSync, existsSync} = require('fs');
const path = require('path');
const {parser} = require('posthtml-parser');
const {match} = require('posthtml/lib/api');
const {match, walk} = require('posthtml/lib/api');
const expressions = require('posthtml-expressions');
const findPathFromTag = require('./find-path');
const processProps = require('./process-props');
const processAttributes = require('./process-attributes');
const {processPushes, processStacks} = require('./process-stacks');
const {setFilledSlots, processSlotContent, processFillContent} = require('./process-slots');
const log = require('./log');
const each = require('lodash/each');
const defaults = require('lodash/defaults');
const assignWith = require('lodash/assignWith');
Expand All @@ -24,14 +25,9 @@ const isBoolean = require('lodash/isBoolean');
const isUndefined = require('lodash/isUndefined'); // value === undefined
const isNull = require('lodash/isNull'); // value === null
const isNil = require('lodash/isNil'); // value == null

// const {inspect} = require('util');
// const debug = true;
// const log = (object, what, method) => {
// if (debug === true || method === debug) {
// console.log(what, inspect(object, false, null, true));
// }
// };
const uniqueId = require('lodash/uniqueId');
const transform = require('lodash/transform');
const assign = require('lodash/assign');

/* eslint-disable complexity */
module.exports = (options = {}) => tree => {
Expand Down Expand Up @@ -71,7 +67,9 @@ module.exports = (options = {}) => tree => {
isBoolean,
isUndefined,
isNull,
isNil
isNil,
uniqueId,
isEnabled: prop => prop === true || prop === ''
};

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

options.props = {...options.expressions.locals};
options.aware = {};

const pushedContent = {};

log('Start of processing..', 'init', 'success');

return processStacks(
processPushes(
processTree(options)(
Expand All @@ -137,21 +138,27 @@ module.exports = (options = {}) => tree => {
};
/* eslint-enable complexity */

// Used for reset aware props
let processCounter = 0;

/**
* @param {Object} options Plugin options
* @return {Object} PostHTML tree
*/
let processCounter = 0;

function processTree(options) {
const filledSlots = {};

return function (tree) {
log(`Processing tree number ${processCounter}..`, 'processTree');

if (options.plugins.length > 0) {
tree = applyPluginsToTree(tree, options.plugins);
}

match.call(tree, options.matcher, currentNode => {
log(`Match found for tag "${currentNode.tag}"..`, 'processTree');

if (!currentNode.attrs) {
currentNode.attrs = {};
}
Expand All @@ -162,24 +169,21 @@ function processTree(options) {
return currentNode;
}

console.log(`${++processCounter}) Processing "${currentNode.tag}" component from "${componentPath}"`);

// log(currentNode, 'currentNode');
log(`${++processCounter}) Processing "${currentNode.tag}" from "${componentPath}"`, 'processTree');

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

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

// Reset options.aware when new nested start
if (processCounter === 1) {
options.aware = {};
}
const aware = transform(options.aware, (result, value) => {
assign(result, value);
}, {});

// Reset options.expressions.locals and keep aware locals
options.expressions.locals = {...options.props, ...options.aware};
options.expressions.locals = {...options.props, ...aware};

const {attributes, props} = processProps(currentNode, nextNode, filledSlots, options, componentPath);
const {attributes, props} = processProps(currentNode, nextNode, filledSlots, options, componentPath, processCounter);

options.expressions.locals = attributes;
options.expressions.locals.$slots = filledSlots;
Expand Down Expand Up @@ -208,14 +212,37 @@ function processTree(options) {
currentNode.tag = false;
currentNode.content = content;

processAttributes(currentNode, attributes, props, options);
processAttributes(currentNode, attributes, props, options, aware);

// Remove attributes when value is 'null' or 'undefined'
// so we can conditionally add an attribute by setting value to 'undefined' or 'null'.
walk.call(currentNode, node => {
if (node && node.attrs) {
each(node.attrs, (value, key) => {
if (['undefined', 'null'].includes(value)) {
delete node.attrs[key];
}
});
}

return node;
});

log(`Done processing number ${processCounter}.`, 'processTree', 'success');

// Reset options.aware for current processCounter
delete options.aware[processCounter];

// Reset counter
processCounter = 0;
// Decrement counter
processCounter--;

return currentNode;
});

if (processCounter === 0) {
log('End of processing', 'processTree', 'success');
}

return tree;
};
}
Expand Down
27 changes: 27 additions & 0 deletions src/log.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const {inspect} = require('util');

const debug = false;

// Colors
const colors = {
reset: '\u001B[0m',
error: '\u001B[31m',
success: '\u001B[32m',
warning: '\u001B[33m',

errorHighlight: '\u001B[41m',
successHighlight: '\u001B[42m',
warningHighlight: '\u001B[43m',

highlighted: '\u001B[45m'
};

module.exports = (message, method, level = 'reset', object = null) => {
if (debug === true || method === debug) {
if (object) {
console.log(`[${colors.highlighted}x-components ${method}()${colors.reset}]`, colors[level] || 'reset', message, inspect(object, false, null, true), colors.reset);
} else {
console.log(`[${colors.highlighted}x-components ${method}()${colors.reset}]`, colors[level] || 'reset', message, colors.reset);
}
}
};
14 changes: 7 additions & 7 deletions src/process-attributes.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ const isObject = require('lodash/isObject');
* @param {Object} attributes
* @param {Object} props
* @param {Object} options
* @param {Object} aware
* @return {void}
*/
module.exports = (currentNode, attributes, props, options) => {
module.exports = (currentNode, attributes, props, options, aware) => {
let mainNode;
match.call(currentNode, {attrs: {attributes: ''}}, node => {
delete node.attrs.attributes;
Expand All @@ -42,7 +43,7 @@ module.exports = (currentNode, attributes, props, options) => {

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

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

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

// Remove an attribute if value is 'null' or 'undefined'
// so we can conditionally add an attribute
// The plugin posthtml-attrs-parser compose() method expects a string,
// but since we are JSON parsing, values like "-1" become number -1.
// So below we convert non string values to string.
each(nodeAttrs, (value, key) => {
if (['undefined', 'null'].includes(value)) {
delete nodeAttrs[key];
} else if (key !== 'compose' && !isObject(nodeAttrs[key]) && !isString(nodeAttrs[key])) {
if (key !== 'compose' && !isObject(nodeAttrs[key]) && !isString(nodeAttrs[key])) {
nodeAttrs[key] = nodeAttrs[key].toString();
}
});
Expand Down
5 changes: 3 additions & 2 deletions src/process-props.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ const attributeTypes = ['aware', 'merge'];
* @param {Object} filledSlots - Filled slots
* @param {Object} options - Plugin options
* @param {string} componentPath - Component path
* @param {number} processCounter
* @return {Object} - Attribute props and script props
*/
module.exports = (currentNode, nextNode, filledSlots, options, componentPath) => {
module.exports = (currentNode, nextNode, filledSlots, options, componentPath, processCounter) => {
let attributes = {...currentNode.attrs};

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

// Set aware attributes
if (attributesByTypeName.aware.length > 0) {
options.aware = pick(attributes, attributesByTypeName.aware);
options.aware[processCounter] = pick(attributes, attributesByTypeName.aware);
}

return {attributes, props};
Expand Down
Loading

0 comments on commit f967aa3

Please sign in to comment.