From 1ba7413cec80a87bbef9c3934e1a68366c7bde24 Mon Sep 17 00:00:00 2001 From: dasiux Date: Sat, 30 Oct 2021 23:29:55 +0200 Subject: [PATCH] update docs + rename navItemActive + updated example + added dev mode --- CHANGELOG.md | 10 +- README.md | 197 ++++++++++++++---- example/data/docs.json | 2 +- example/data/index.json | 14 +- example/fragments/docs/table-of-contents.json | 29 --- example/fragments/header.json | 4 +- example/fragments/table-of-contents.json | 46 ++++ example/plugins/example.js | 4 +- example/templates/partials/styles.twig | 5 +- package.json | 2 +- src/classes/TwigHouse.js | 33 ++- src/cli.js | 5 +- .../{navItemActive.js => isDocValue.js} | 17 +- 13 files changed, 279 insertions(+), 89 deletions(-) delete mode 100644 example/fragments/docs/table-of-contents.json create mode 100644 example/fragments/table-of-contents.json rename src/directives/{navItemActive.js => isDocValue.js} (60%) diff --git a/CHANGELOG.md b/CHANGELOG.md index f85ed0b..94d8960 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog -## 0.8.3 - - Cleaned up error handling and output, added interactive mode, fixed setFromDoc directive for unknown uri/url. +## 0.8.4 + - Cleaned up error handling and output, added interactive mode, fixed setFromDoc directive for unknown uri/url, renamed navItemActive to isDocValue and added more docs. ## 0.7.8 - Added document object and setFromDoc directive performed some cleanups. @@ -12,8 +12,14 @@ ## 0.6.0 - Complete restructure, still missing docs update, most options still work as before. + [github restructure release](https://github.com/squirrel-forge/node-twighouse/releases/tag/0.6.0) + ## 0.3.0 - Some docs, more example data, templates and plugin details. + [github alpha release](https://github.com/squirrel-forge/node-twighouse/releases/tag/0.3.0) + + [npm alpha release](https://www.npmjs.com/package/@squirrel-forge/twighouse/v/0.3.0) + ## 0.2.0 - Core features prototype. diff --git a/README.md b/README.md index 7283bf2..2b2a594 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,14 @@ A simple, but extendable, json+twig render tool for node. +Let's start off with a fitting quote to keep in mind when writing code: + ``` "You can't suddenly know something, just by assembling a committee of words." ``` *Hubert J. Farnsworth* -If you wish to know more about why I am making this tool, read my [personal note](#personal-note) or talk to me on twitter *@dasiux*. +If you wish to know more about why I am making this tool, read my [personal note](#personal-note), if you have questions talk to me on twitter [@dasiux](https://twitter.com/dasiux). ## Installation @@ -76,13 +78,13 @@ A long option always override the value of a short option if both are used. You can use urls in certain parts of the application, this example will render using local templates, but loads its data and fragments from urls. Check the [planned features](#planned-features-bugs-and-fixes) for updates. ``` -twighouse example dist -c=https://raw.githubusercontent.com/squirrel-forge/node-twighouse/main/example/data/index.json -d=https://raw.githubusercontent.com/squirrel-forge/node-twighouse/main/example/data -f=https://raw.githubusercontent.com/squirrel-forge/node-twighouse/main/example/fragments -m +twighouse example dist -c=https://raw.githubusercontent.com/squirrel-forge/node-twighouse/main/example/data/index.json -d=https://raw.githubusercontent.com/squirrel-forge/node-twighouse/main/example/data -f=https://raw.githubusercontent.com/squirrel-forge/node-twighouse/main/example/fragments -m -u ``` If you wish to use the source argument as an url base you must set the target argument, the template and the plugins option with an absolute path, the *.twighouse* config will be loaded from the current working directory. ``` -twighouse https://raw.githubusercontent.com/squirrel-forge/node-twighouse/main/example /{...}/dist -p=/{...}/example/plugins -t=/{...}/example/templates -c=data/index.json -m +twighouse https://raw.githubusercontent.com/squirrel-forge/node-twighouse/main/example /{...}/dist -p=/{...}/example/plugins -t=/{...}/example/templates -c=data/index.json -m -u ``` @@ -102,15 +104,23 @@ Assume following data structure from the example build: | `-- index.json | +-- [fragments] - | | + | | | |-- footer.json | |-- header.json | |-- meta.json - | `-- styles.json + | |-- styles.json + | `-- table-of-contents.json | +-- [plugin_methods] | | - | `-- exampleLoader.js + | |-- exampleData.js + | |-- exampleDirectiveAsync.js + | |-- exampleDirectiveSync.js + | |-- exampleDoc.js + | |-- exampleHTML.js + | |-- exampleLoader.js + | |-- exampleTemplate.js + | `-- exampleTwig.js | +-- [plugins] | @@ -120,24 +130,26 @@ Assume following data structure from the example build: ### Special properties -In general you will define what you need, there are only a few special properties that can be used. -All of these can be set via the *.twighouse* config file options. +In general, you will define what you need, there are only a few special properties that can be used. +All of these can be customized via the *.twighouse* [config file options](#configuration-options). ### Page template - - The *__template* property is described [here](#loading-templates) and must be on the root object. +The *__template* property is described [here](#loading-templates) and must be on the root object. + ``` { "__template": "{.../}template" } ``` - - The *document* property gets defined before json processing and is set afterwards and may be modified via the [plugin data](#plugin-data) method. Note that the document data object is supplied to any [directives](#directives) running during processing. + +### Minify options + +Every page can have custom minify options, only used when minify is enabled. You can find an options reference at the [html-minifier](https://www.npmjs.com/package/html-minifier#options-quick-reference) npm page. + ``` { - path: {string} The page reference, includes a full relativ path and the page slug - dir: {string} The relative path of this page - slug: {string} The page slug - uri: {string} The generated page uri + "minify": {...} } ``` @@ -151,37 +163,148 @@ For explicit examples check the example source. ### Document object -The TwigHouseDocument object has the following properties +The *document* property gets defined before json processing and is set afterwards and may be modified via the [plugin data](#plugin-data) method, but this might cause errors in structure, do not remove or replace the object. Note that *the document object* is supplied to any [directives](#directives) running during processing. - Name | Type | Description -------|------|--- - path | str | Document path relative to root - dir | str | Directory relative to root - slug | str | Document name - uri | str | Document uri +The TwigHouseDocument object has the following properties, they should be treated as read only, but can be modified with unexpected results. + +``` +{ + document: TwigHouseDocument: { + source : 'root/path/file', + root : 'root/path', + slug : 'document-slug', + dir : 'relative/to/root', + ref : 'dir/slug', + uri : 'generated.uri', + url : 'generated.url', + } +} + +``` The document object is added to every page data object and should not be used in the json source since it will get deleted. ### Directives -Directives can modify properties and objects in the defined context of your pages json data, directives can be defined via [plugin directives](#plugin-directives) inside a [plugin](#plugins) or the [api](#api-usage) and can be used as following: +Directives can modify properties and objects in the defined context of your pages json data, directives can be defined via [plugin directives](#plugin-directives) inside a [plugin](#plugins) or the [api](#api-usage). Directive name and argument are separated by colons, the first argument is always the target property. They can be used as following: ``` { - "__directives": ["directive_method_name:property_to_use:additional_arguments", ...], + "__directives": ["directive_method_name:property_to_use:additional_arguments", ...directives], "property_to_use": "*", ... } ``` -Directives are always executed in the defined order, which lets you chain them to modify in steps. +Directives are always executed in the defined order, which lets you chain them to modify values in steps, as can be seen in the demo, first loading the an *.md* file from a path and then converting the files content to html. -#### Available directives +#### Builtin directives A list of builtin directives an how they can be used. -##### Directive navItemActive +#### Directive isDocValue + +Compares a property to the [document object](#document-object) and sets a property to *true* if the values are equal, used to set nav items active state for example. + +All directive arguments are property names: + +Name | Description +-------- | --- + compare | Property to compare, default: 'uri' + prop | Property to set if equal, default: 'active' + value | Value to set, default: true + +Single object: + +``` +// Input +{ + "__directives": ["isDocValue:uri"], + "uri": "/" +} + +// Result, assuming the current document is: index +{ + "__directives": ["isDocValue:uri"], + "uri": "/", + "active": true +} + +``` + +Array of objects: + +``` +// Input +{ + "__directives": ["isDocValue:items"], + "items": [ + {"uri": "/docs.html"}, + {"uri": "/changelog.html"} + ] +} + +// Result, assuming the current document is: docs +{ + "__directives": ["isDocValue:items"], + "items": [ + {"uri": "/docs.html", "active": true}, + {"uri": "/changelog.html"} + ] +} + +``` + +#### Directive setFromDoc + +Reads a property with a document reference and sets a property with a specified property, used to set uri/url properties for document references inside the source tree. + +All directive arguments are property names: + +Name | Description +----- | --- + get | Property to read document reference from, default: 'uri' + set | Property to set value on, default: {get} + type | Document object property value to set, default: {set} + +Single object: + +``` +// Input +{ + "__directives": ["setFromDoc:uri"], + "uri": "index", +} -... +// Result +{ + "__directives": ["setFromDoc:uri"], + "uri": "/", +} + +``` + +Array of objects: + +``` +// Input +{ + "__directives": ["setFromDoc:items"], + "items": [ + {"uri": "docs"}, + {"uri": "changelog"} + ] +} + +// Result +{ + "__directives": ["setFromDoc:items"], + "items": [ + {"uri": "/docs.html"}, + {"uri": "/changelog.html"} + ] +} + +``` ## Templates @@ -235,10 +358,10 @@ A project directory can make use of a *.twighouse* json config file to reduce th These can be set via the *.twighouse* json config or with the api from a plugin or your own application. Name | Type | Default | Description ---------------------|--------|----------------|--- - verbose | bool | false | Run in verbose mode +------------------- | ------ | ---------------| --- + verbose | bool | false | Run in verbose mode (cannot be set via config file) strict | bool | false | Run in strict mode - silent | bool | false | Silent mode will prevent any output and should be used with strict = true + silent | bool | false | Silent mode will prevent any output and should be used with strict = true (cannot be set via config file) root | str | '' | Source directory, empty is the current working directory data | str | 'data' | Data directory, if not absolute it will be attached to the root option fragments | str | 'fragments' | Fragments directory, @@ -270,7 +393,7 @@ You may also set node module names in the usePlugins configuration option to loa Plugins can be supplied in three ways, class constructors, class instance or plain object. -#### Plugin type: plain object +#### Plugin type: Plain object The plain object plugin is the simplest form, a basic structure, for details please refer to the example plugin. @@ -315,7 +438,7 @@ module.exports = { ``` -#### Plugin type: class constructor +#### Plugin type: Class constructor The class plugin will use the constructors name as reference, all method, directives, loaders, etc. need to be set in the constructor method via the TwigHouse instance. @@ -340,7 +463,7 @@ module.exports = class Example { ``` -#### Plugin type: class instance +#### Plugin type: Class instance The class instance plugin will have the gains of using a class combined with the features of a plain object plugin with automatic assignment. @@ -480,7 +603,7 @@ Directives can be registered the following way, see how to define [directives](# Activate a builtin directive, see the [directives](#available-directives) list for available names. ``` -twigH.useDirective( 'navItemActive' ); +twigH.useDirective( 'isDocValue' ); ``` @@ -494,7 +617,7 @@ Registering a custom directive, they can be sync or async functions or may retur * @param {Object} parent - Property parent * @param {TwigHouseDocument} doc - Document object * @param {TwigHouse} twigH - TwigHouse instance - * @param {...} ... + * @param {...} ... - Any additional arguments * @return {void} */ function directive( text, key, parent, doc, twigH ) { @@ -507,7 +630,7 @@ twigH.registerDirective( 'name', directive ); ## Api usage -You can require the TwigHouse class in your node script and run it, change internal options and extend it easily. +You can require the TwigHouse class in your node script and run it, change internal options and extend it easily, look at the cli implementation and code comments to understand what to run in which order. ``` const TwigHouse = require('@squirrel-forge/twighouse'); @@ -528,7 +651,7 @@ I have written a lot of code over the years and one thing that always returned, ## Planned features, bugs and fixes -Whenever there is time and space. Bugs and fixes will always get priority above feature requests, as long as the bug is severe and cannot be solved with a workaround. Why is everything open to read and extend? It enables you to do anything you like and yes, break things in the process, but what's the worst that can happen? You understand why, learn something or even help others understand. +Whenever there is time and space. Bugs and fixes will always get priority above feature requests, as long as the bug is severe and cannot be solved with a simple workaround. Why is everything open to read and extend? It enables you to do anything you like and yes, break things in the process, but what's the worst that can happen? You understand why, learn something or even help others understand, and hopefully make twighouse better. **Upcoming features** (in no specific order) - Remote template loading? is it possible with twig extends and includes etc? diff --git a/example/data/docs.json b/example/data/docs.json index 810641d..35d192e 100644 --- a/example/data/docs.json +++ b/example/data/docs.json @@ -10,7 +10,7 @@ "__fragment": "footer" }, "aside": { - "__fragment": "docs/table-of-contents" + "__fragment": "table-of-contents" }, "content": [ { diff --git a/example/data/index.json b/example/data/index.json index a546c6f..e4150ed 100644 --- a/example/data/index.json +++ b/example/data/index.json @@ -11,7 +11,19 @@ "content": [ { "__component": "section", - "content": "

@squirrel-forge/twighouse

A simple, but extendable, json+twig render tool for node.

twig & json

This page was generated using a few twig templates and some json files.
Check the docs or the code for more details.

" + "content": "

@squirrel-forge/twighouse

A simple, but extendable, json+twig render tool for node.

" + }, + { + "__component": "section", + "content": "

node, twig & json

This page was generated using a few twig templates and some json files.
Check the docs or the code for more details.

" + }, + { + "__component": "section", + "content": "

Feedback and support

I will do my best to keep up to date with the docs, if you need help that is not covered and you can't find answers in the code comments feel free to contact me on twitter @dasiux.

" + }, + { + "__component": "section", + "content": "

Issues, feature and plugin requests

Whenever there is time and space. Bugs and fixes will always get priority above feature requests, as long as the bug is severe and cannot be solved with a simple workaround. Why is everything open to read and extend? It enables you to do anything you like and yes, break things in the process, but what's the worst that can happen? You understand why, learn something or even help others understand, and hopefully make twighouse better.

dan aka siux

" } ], "styles": { diff --git a/example/fragments/docs/table-of-contents.json b/example/fragments/docs/table-of-contents.json deleted file mode 100644 index 8cead45..0000000 --- a/example/fragments/docs/table-of-contents.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "__component": "aside", - "content": [ - "

Overview

", - { - "__component": "nav", - "items": [ - {"uri": "#installation", "label": "Installation"}, - {"uri": "#quickstart", "label": "Quickstart","indent": 1}, - {"uri": "#cli-usage", "label": "cli usage"}, - {"uri": "#arguments", "label": "Arguments","indent": 1}, - {"uri": "#options", "label": "Options","indent": 1}, - {"uri": "#json-input", "label": "JSON input"}, - {"uri": "#special-properties", "label": "Properties","indent": 1}, - {"uri": "#fragments", "label": "Fragments","indent": 1}, - {"uri": "#directives", "label": "Directives","indent": 1}, - {"uri": "#templates", "label": "Templates"}, - {"uri": "#loading-templates", "label": "Loading","indent": 1}, - {"uri": "#plugins", "label": "Plugins"}, - {"uri": "#methods", "label": "Methods","indent": 1}, - {"uri": "#adding-directives", "label": "Directives","indent": 1}, - {"uri": "#api-usage", "label": "Api usage"}, - {"uri": "#setting-arguments-and-options", "label": "Args & Opts","indent": 1}, - {"uri": "#adding-plugin-methods", "label": "Plugins","indent": 1}, - {"uri": "#adding-directives", "label": "Directives","indent": 1} - ] - } - ] -} diff --git a/example/fragments/header.json b/example/fragments/header.json index cf6cabb..48b1096 100644 --- a/example/fragments/header.json +++ b/example/fragments/header.json @@ -1,11 +1,11 @@ { "home": { - "__directives": ["setFromDoc:uri", "navItemActive:uri"], + "__directives": ["setFromDoc:uri", "isDocValue:uri"], "uri": "index", "label": "@squirrel-forge/twighouse" }, "nav": { - "__directives": ["setFromDoc:items", "navItemActive:items"], + "__directives": ["setFromDoc:items", "isDocValue:items"], "items": [ {"uri": "docs", "label": "docs"}, {"uri": "changelog", "label": "changes"}, diff --git a/example/fragments/table-of-contents.json b/example/fragments/table-of-contents.json new file mode 100644 index 0000000..8994e30 --- /dev/null +++ b/example/fragments/table-of-contents.json @@ -0,0 +1,46 @@ +{ + "__component": "aside", + "content": [ + "

Overview

", + { + "__component": "nav", + "items": [ + {"uri": "#installation", "label": "Installation"}, + {"uri": "#quickstart", "label": "Quickstart","indent": 1}, + {"uri": "#cli-usage", "label": "cli usage"}, + {"uri": "#arguments", "label": "Arguments","indent": 1}, + {"uri": "#options", "label": "Options","indent": 1}, + {"uri": "#using-url-data", "label": "Using Urls","indent": 1}, + {"uri": "#json-input", "label": "JSON input"}, + {"uri": "#special-properties", "label": "Properties","indent": 1}, + {"uri": "#page-template", "label": "Template","indent": 2}, + {"uri": "#minify-options", "label": "Minify","indent": 2}, + {"uri": "#fragments", "label": "Fragments","indent": 2}, + {"uri": "#document-object", "label": "Document","indent": 2}, + {"uri": "#directives", "label": "Directives","indent": 1}, + {"uri": "#builtin-directives", "label": "Builtin","indent": 2}, + {"uri": "#directive-isdocvalue", "label": "isDocValue","indent": 2}, + {"uri": "#directive-setfromdoc", "label": "setFromDoc","indent": 2}, + {"uri": "#templates", "label": "Templates"}, + {"uri": "#loading-templates", "label": "Loading","indent": 1}, + {"uri": "#project-config", "label": "Project"}, + {"uri": "#configuration-options", "label": "Configuration","indent": 1}, + {"uri": "#plugins", "label": "Plugins"}, + {"uri": "#plugin-type-plain-object", "label": "Object","indent": 1}, + {"uri": "#plugin-type-class-constructor", "label": "Class","indent": 1}, + {"uri": "#plugin-type-class-instance", "label": "Instance","indent": 1}, + {"uri": "#methods", "label": "Methods","indent": 1}, + {"uri": "#plugin-twig", "label": "Twig","indent": 2}, + {"uri": "#plugin-doc", "label": "Document","indent": 2}, + {"uri": "#plugin-data", "label": "Data","indent": 2}, + {"uri": "#plugin-template", "label": "Template","indent": 2}, + {"uri": "#plugin-html", "label": "HTML","indent": 2}, + {"uri": "#plugin-loader", "label": "Loader","indent": 2}, + {"uri": "#plugin-directives", "label": "Directives","indent": 2}, + {"uri": "#api-usage", "label": "Api usage"}, + {"uri": "#personal-note", "label": "Personal note"}, + {"uri": "#planned-features-bugs-and-fixes", "label": "Features"} + ] + } + ] +} diff --git a/example/plugins/example.js b/example/plugins/example.js index 431a0b1..c143ded 100644 --- a/example/plugins/example.js +++ b/example/plugins/example.js @@ -59,8 +59,8 @@ module.exports = { twigH.plugins.method( 'loader', exampleLoader ); } - // Enable a builtin directive - // twigH.useDirective( 'navItemActive' ); + // Enable a single builtin directive + // twigH.useDirective( 'isDocValue' ); // Or use all directives twigH.registerBuiltinDirectives( 'all' ); diff --git a/example/templates/partials/styles.twig b/example/templates/partials/styles.twig index 5ce2bf8..b028834 100644 --- a/example/templates/partials/styles.twig +++ b/example/templates/partials/styles.twig @@ -139,6 +139,9 @@ nav li[data-indent] { padding-left: 1rem; } + nav li[data-indent="2"] { + padding-left: 2rem; + } aside nav ul { flex-direction: column; } @@ -249,7 +252,7 @@ td:nth-child(1), td:nth-child(2), td:nth-child(3) { - white-space: nowrap; + white-space: pre-wrap; text-align: center; } @media screen and (min-width: 768px) { diff --git a/package.json b/package.json index aea1457..47cc313 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@squirrel-forge/twighouse", - "version": "0.8.3", + "version": "0.8.4", "description": "A simple, but extendable, json+twig render tool for node", "main": "src/classes/TwigHouse.js", "scripts": { diff --git a/src/classes/TwigHouse.js b/src/classes/TwigHouse.js index 30038b0..e5c49b4 100644 --- a/src/classes/TwigHouse.js +++ b/src/classes/TwigHouse.js @@ -79,8 +79,9 @@ class TwigHouse { * Constructor * @constructor * @param {null|console} cfx - Console or alike object + * @param {boolean} dev - Development mode, default: false */ - constructor( cfx = null ) { + constructor( cfx = null, dev = false ) { /** * Console alike reporting object @@ -98,6 +99,14 @@ class TwigHouse { */ this.VERSION = '0.7.4'; + /** + * Development mode + * @protected + * @property + * @type {boolean} + */ + this._dev = dev; + /** * Install location * @public @@ -277,7 +286,7 @@ class TwigHouse { * @property * @type {string[]} */ - this._builtinDirectives = [ 'setFromDoc', 'navItemActive' ]; + this._builtinDirectives = [ 'setFromDoc', 'isDocValue' ]; } /** @@ -502,7 +511,19 @@ class TwigHouse { * @return {Promise} - Loads and assigns config if available */ async _loadConfig() { - const config_path = path.resolve( path.join( isUrl( this._config.root ) ? '' : this._config.root, this._config.__configname ) ); + let config_path; + + // In dev mode always load config from current cwd + if ( this._dev ) { + config_path = path.resolve( path.join( process.cwd(), this._config.__configname ) ); + } + + // Not an absolute path + if ( !config_path || config_path[ 0 ] !== path.sep ) { + + // Assumes current cwd if root is an url + config_path = path.resolve( path.join( isUrl( this._config.root ) ? '' : this._config.root, this._config.__configname ) ); + } const config_exists = await this.fs.exists( config_path ); if ( config_exists ) { if ( this._config.verbose ) { @@ -514,16 +535,18 @@ class TwigHouse { } catch ( e ) { err = e; } - if ( err || !config || typeof config !== 'object' ) { // Always fail if invalid object this.error( new TwigHouseException( 'Failed to load config from: ' + config_path, err ), true ); } else { - // Disallow verbose and silent option + // Disallow options + delete config.__configname; delete config.verbose; delete config.silent; + + // Assign leftover values Object.assign( this._config, config ); } } else if ( this._config.verbose ) { diff --git a/src/cli.js b/src/cli.js index ff6b2c0..198dbc6 100644 --- a/src/cli.js +++ b/src/cli.js @@ -46,6 +46,9 @@ module.exports = async function cli() { // Cli application options const options = input.getFlagsOptions( { + // Development mode + dev : [ '', '--dev', false, true ], + // Show version version : [ '-v', '--version', false, true ], @@ -204,7 +207,7 @@ module.exports = async function cli() { // Construct application // - Set output handler // - Prepare instance - const twigH = new TwigHouse( cfx ); + const twigH = new TwigHouse( cfx, options.dev ); // Deploy example if ( options.example ) { diff --git a/src/directives/navItemActive.js b/src/directives/isDocValue.js similarity index 60% rename from src/directives/navItemActive.js rename to src/directives/isDocValue.js index c51e2d1..ba83e04 100644 --- a/src/directives/navItemActive.js +++ b/src/directives/isDocValue.js @@ -1,32 +1,35 @@ /** - * Directive: nav item active state + * Directive: is document value state * @param {string|Array} items - Item value * @param {string} key - Item key * @param {Object} parent - Item parent * @param {TwigHouseDocument} doc - Document object * @param {TwigHouse} twigH - TwigHouse instance - * @param {string} compare - Property name to compare - * @param {string} prop - Property name to set true on active + * @param {string} compare - Property name to compare, default: 'uri' + * @param {string} prop - Property name to set, default: 'active' + * @param {string} value - Value to set, default: true * @return {void} */ -module.exports = function navItemActive( +module.exports = function isDocValue( items, key, parent, doc, twigH, compare = 'uri', - prop = 'active' + prop = 'active', + value = true, ) { compare = compare || 'uri'; prop = prop || 'active'; + value = value || true; if ( items instanceof Array ) { for ( let i = 0; i < items.length; i++ ) { if ( items[ i ][ compare ] === doc[ compare ] ) { - items[ i ][ prop ] = true; + items[ i ][ prop ] = value; } } } else if ( parent[ compare ] === doc[ compare ] ) { - parent[ prop ] = true; + parent[ prop ] = value; } };