diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..4872c5af --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: +- package-ecosystem: npm + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 diff --git a/build.sh b/build.sh index 0f7e47db..faf72ade 100755 --- a/build.sh +++ b/build.sh @@ -10,7 +10,7 @@ then fi # Generate the docs using daux.io -if vendor/bin/daux generate --source=. --destination=html ; then +if php vendor/bin/daux generate --source=. --destination=html ; then # Remove the empty placeholder file from the generated html folder if [ -f html/modmore-documentation.zip ]; @@ -19,7 +19,7 @@ if vendor/bin/daux generate --source=. --destination=html ; then fi # Generate a zip file containing the complete static site, placing it inside the html folder again - zip -r html/modmore-documentation.zip html + #zip -r html/modmore-documentation.zip html else echo "Failed generating documentation"; exit 1; @@ -32,4 +32,4 @@ rm -rf html/themes; # Create symlink to central themes folder cd html; ln -s ../themes/ themes; cd ..; -echo "Build complete!"; \ No newline at end of file +echo "Build complete!"; diff --git a/composer.json b/composer.json index 411e1810..1ed16e13 100644 --- a/composer.json +++ b/composer.json @@ -1,5 +1,10 @@ { + "config": { + "platform": { + "php": "7.4" + } + }, "require": { - "justinwalsh/daux.io": "dev-development" + "daux/daux.io": "0.x" } } diff --git a/composer.lock b/composer.lock index 7cc17496..8a36f455 100644 --- a/composer.lock +++ b/composer.lock @@ -1,40 +1,203 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "hash": "0389a259cd183bd7d9f213ffbe46b84b", - "content-hash": "e99e6338b927a9955825a72070b3b104", + "content-hash": "11fdb4e4b554a7045cad2f25afe4b346", "packages": [ + { + "name": "daux/daux.io", + "version": "0.17.2", + "source": { + "type": "git", + "url": "https://github.com/dauxio/daux.io.git", + "reference": "ef1a72ce597c70fc863ef117ae842cd93699aac6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dauxio/daux.io/zipball/ef1a72ce597c70fc863ef117ae842cd93699aac6", + "reference": "ef1a72ce597c70fc863ef117ae842cd93699aac6", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/guzzle": "~6.0 || ~7.0", + "league/commonmark": "^2.0.0", + "league/plates": "~3.1", + "php": ">=7.4", + "scrivo/highlight.php": "^9.15", + "symfony/console": "^4.4|^5.0", + "symfony/http-foundation": "^4.4|^5.0", + "symfony/mime": "^4.4|^5.0", + "symfony/polyfill-intl-icu": "^1.10", + "symfony/process": "^4.4|^5.0", + "symfony/yaml": "^4.4|^5.0" + }, + "replace": { + "justinwalsh/daux.io": "*" + }, + "require-dev": { + "mikey179/vfsstream": "^1.6" + }, + "suggest": { + "ext-intl": "Allows to translate the modified at date" + }, + "bin": [ + "bin/daux" + ], + "type": "project", + "autoload": { + "psr-4": { + "Todaymade\\Daux\\": "libs/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Stéphane Goetz", + "homepage": "http://onigoetz.ch/" + }, + { + "name": "Justin Walsh", + "homepage": "http://todaymade.com/" + } + ], + "description": "Documentation generator that uses a simple folder structure and Markdown files to create custom documentation on the fly", + "homepage": "https://dauxio.github.io/", + "keywords": [ + "docs", + "documentation", + "markdown", + "md" + ], + "support": { + "issues": "https://github.com/dauxio/daux.io/issues", + "source": "https://github.com/dauxio/daux.io/tree/0.17.2" + }, + "time": "2022-01-03T20:27:17+00:00" + }, + { + "name": "dflydev/dot-access-data", + "version": "v3.0.3", + "source": { + "type": "git", + "url": "https://github.com/dflydev/dflydev-dot-access-data.git", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.3", + "scrutinizer/ocular": "1.6.0", + "squizlabs/php_codesniffer": "^3.5", + "vimeo/psalm": "^4.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Dflydev\\DotAccessData\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dragonfly Development Inc.", + "email": "info@dflydev.com", + "homepage": "http://dflydev.com" + }, + { + "name": "Beau Simensen", + "email": "beau@dflydev.com", + "homepage": "http://beausimensen.com" + }, + { + "name": "Carlos Frutos", + "email": "carlos@kiwing.it", + "homepage": "https://github.com/cfrutos" + }, + { + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com" + } + ], + "description": "Given a deep data structure, access data by dot notation.", + "homepage": "https://github.com/dflydev/dflydev-dot-access-data", + "keywords": [ + "access", + "data", + "dot", + "notation" + ], + "support": { + "issues": "https://github.com/dflydev/dflydev-dot-access-data/issues", + "source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3" + }, + "time": "2024-07-08T12:26:09+00:00" + }, { "name": "guzzlehttp/guzzle", - "version": "6.2.3", + "version": "7.10.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006" + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/8d6c6cc55186db87b7dc5009827429ba4e9dc006", - "reference": "8d6c6cc55186db87b7dc5009827429ba4e9dc006", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", + "reference": "b51ac707cfa420b7bfd4e4d5e510ba8008e822b4", "shasum": "" }, "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.4", - "php": ">=5.5" + "ext-json": "*", + "guzzlehttp/promises": "^2.3", + "guzzlehttp/psr7": "^2.8", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0", + "symfony/deprecation-contracts": "^2.2 || ^3.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.2", "ext-curl": "*", - "phpunit/phpunit": "^4.0", - "psr/log": "^1.0" + "guzzle/client-integration-tests": "3.0.2", + "php-http/message-factory": "^1.1", + "phpunit/phpunit": "^8.5.39 || ^9.6.20", + "psr/log": "^1.1 || ^2.0 || ^3.0" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "6.2-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { @@ -50,246 +213,415 @@ "MIT" ], "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" + }, + { + "name": "Jeremy Lindblom", + "email": "jeremeamia@gmail.com", + "homepage": "https://github.com/jeremeamia" + }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" } ], "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", "keywords": [ "client", "curl", "framework", "http", "http client", + "psr-18", + "psr-7", "rest", "web service" ], - "time": "2017-02-28 22:50:30" + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.10.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/guzzle", + "type": "tidelift" + } + ], + "time": "2025-08-23T22:36:01+00:00" }, { "name": "guzzlehttp/promises", - "version": "v1.3.1", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + "reference": "481557b130ef3790cf82b713667b43030dc9c957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "url": "https://api.github.com/repos/guzzle/promises/zipball/481557b130ef3790cf82b713667b43030dc9c957", + "reference": "481557b130ef3790cf82b713667b43030dc9c957", "shasum": "" }, "require": { - "php": ">=5.5.0" + "php": "^7.2.5 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^4.0" + "bamarni/composer-bin-plugin": "^1.8.2", + "phpunit/phpunit": "^8.5.44 || ^9.6.25" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.4-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { "psr-4": { "GuzzleHttp\\Promise\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", + "homepage": "https://github.com/Tobion" } ], "description": "Guzzle promises library", "keywords": [ "promise" ], - "time": "2016-12-20 10:07:11" + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/2.3.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/promises", + "type": "tidelift" + } + ], + "time": "2025-08-22T14:34:08+00:00" }, { "name": "guzzlehttp/psr7", - "version": "1.4.2", + "version": "2.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + "reference": "21dc724a0583619cd1652f673303492272778051" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/21dc724a0583619cd1652f673303492272778051", + "reference": "21dc724a0583619cd1652f673303492272778051", "shasum": "" }, "require": { - "php": ">=5.4.0", - "psr/http-message": "~1.0" + "php": "^7.2.5 || ^8.0", + "psr/http-factory": "^1.0", + "psr/http-message": "^1.1 || ^2.0", + "ralouphie/getallheaders": "^3.0" }, "provide": { + "psr/http-factory-implementation": "1.0", "psr/http-message-implementation": "1.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "bamarni/composer-bin-plugin": "^1.8.2", + "http-interop/http-factory-tests": "0.9.0", + "phpunit/phpunit": "^8.5.44 || ^9.6.25" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.4-dev" + "bamarni-bin": { + "bin-links": true, + "forward-command": false } }, "autoload": { "psr-4": { "GuzzleHttp\\Psr7\\": "src/" - }, - "files": [ - "src/functions_include.php" - ] + } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ + { + "name": "Graham Campbell", + "email": "hello@gjcampbell.co.uk", + "homepage": "https://github.com/GrahamCampbell" + }, { "name": "Michael Dowling", "email": "mtdowling@gmail.com", "homepage": "https://github.com/mtdowling" }, + { + "name": "George Mponos", + "email": "gmponos@gmail.com", + "homepage": "https://github.com/gmponos" + }, + { + "name": "Tobias Nyholm", + "email": "tobias.nyholm@gmail.com", + "homepage": "https://github.com/Nyholm" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://github.com/sagikazarmark" + }, { "name": "Tobias Schultze", + "email": "webmaster@tubo-world.de", "homepage": "https://github.com/Tobion" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" } ], "description": "PSR-7 message implementation that also provides common utility methods", "keywords": [ "http", "message", + "psr-7", "request", "response", "stream", "uri", "url" ], - "time": "2017-03-20 17:10:46" + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/2.8.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7", + "type": "tidelift" + } + ], + "time": "2025-08-23T21:21:41+00:00" }, { - "name": "justinwalsh/daux.io", - "version": "dev-development", + "name": "league/commonmark", + "version": "2.8.0", "source": { "type": "git", - "url": "https://github.com/justinwalsh/daux.io.git", - "reference": "0966d18839cd732e780056467a82f372904e0e5d" + "url": "https://github.com/thephpleague/commonmark.git", + "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/justinwalsh/daux.io/zipball/0966d18839cd732e780056467a82f372904e0e5d", - "reference": "0966d18839cd732e780056467a82f372904e0e5d", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/4efa10c1e56488e658d10adf7b7b7dcd19940bfb", + "reference": "4efa10c1e56488e658d10adf7b7b7dcd19940bfb", "shasum": "" }, "require": { - "guzzlehttp/guzzle": "~6.0", - "league/commonmark": "^0.15", - "league/plates": "~3.1", - "myclabs/deep-copy": "^1.5", - "php": ">=5.5", - "symfony/console": "~3.0", - "symfony/finder": "~3.0", - "symfony/process": "^3.1", - "webuni/commonmark-table-extension": "0.6.*", - "webuni/front-matter": "^1.0.0" + "ext-mbstring": "*", + "league/config": "^1.1.1", + "php": "^7.4 || ^8.0", + "psr/event-dispatcher": "^1.0", + "symfony/deprecation-contracts": "^2.1 || ^3.0", + "symfony/polyfill-php80": "^1.16" }, "require-dev": { - "mikey179/vfsstream": "^1.6", - "phpunit/phpunit": "~4" + "cebe/markdown": "^1.0", + "commonmark/cmark": "0.31.1", + "commonmark/commonmark.js": "0.31.1", + "composer/package-versions-deprecated": "^1.8", + "embed/embed": "^4.4", + "erusev/parsedown": "^1.0", + "ext-json": "*", + "github/gfm": "0.29.0", + "michelf/php-markdown": "^1.4 || ^2.0", + "nyholm/psr7": "^1.5", + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", + "scrutinizer/ocular": "^1.8.1", + "symfony/finder": "^5.3 | ^6.0 | ^7.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", + "unleashedtech/php-coding-standard": "^3.1.1", + "vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0" + }, + "suggest": { + "symfony/yaml": "v2.3+ required if using the Front Matter extension" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.9-dev" + } }, - "bin": [ - "bin/daux" - ], - "type": "project", "autoload": { "psr-4": { - "Todaymade\\Daux\\": "libs/" + "League\\CommonMark\\": "src" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause" ], "authors": [ { - "name": "Justin Walsh", - "homepage": "http://todaymade.com/" + "name": "Colin O'Dell", + "email": "colinodell@gmail.com", + "homepage": "https://www.colinodell.com", + "role": "Lead Developer" } ], - "description": "Documentation generator that uses a simple folder structure and Markdown files to create custom documentation on the fly", - "homepage": "http://daux.io/", + "description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)", + "homepage": "https://commonmark.thephpleague.com", "keywords": [ - "docs", - "documentation", + "commonmark", + "flavored", + "gfm", + "github", + "github-flavored", "markdown", - "md" + "md", + "parser" + ], + "support": { + "docs": "https://commonmark.thephpleague.com/", + "forum": "https://github.com/thephpleague/commonmark/discussions", + "issues": "https://github.com/thephpleague/commonmark/issues", + "rss": "https://github.com/thephpleague/commonmark/releases.atom", + "source": "https://github.com/thephpleague/commonmark" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/commonmark", + "type": "tidelift" + } ], - "time": "2017-03-02 17:17:29" + "time": "2025-11-26T21:48:24+00:00" }, { - "name": "league/commonmark", - "version": "0.15.3", + "name": "league/config", + "version": "v1.2.0", "source": { "type": "git", - "url": "https://github.com/thephpleague/commonmark.git", - "reference": "c8b43ee5821362216f8e9ac684f0f59de164edcc" + "url": "https://github.com/thephpleague/config.git", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/c8b43ee5821362216f8e9ac684f0f59de164edcc", - "reference": "c8b43ee5821362216f8e9ac684f0f59de164edcc", + "url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", + "reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3", "shasum": "" }, "require": { - "ext-mbstring": "*", - "php": ">=5.4.8" - }, - "replace": { - "colinodell/commonmark-php": "*" + "dflydev/dot-access-data": "^3.0.1", + "nette/schema": "^1.2", + "php": "^7.4 || ^8.0" }, "require-dev": { - "cebe/markdown": "~1.0", - "erusev/parsedown": "~1.0", - "jgm/commonmark": "0.27", - "michelf/php-markdown": "~1.4", - "mikehaertl/php-shellcommand": "~1.2.0", - "phpunit/phpunit": "~4.3|~5.0", - "scrutinizer/ocular": "~1.1", - "symfony/finder": "~2.3|~3.0" - }, - "suggest": { - "league/commonmark-extras": "Library of useful extensions including smart punctuation" + "phpstan/phpstan": "^1.8.2", + "phpunit/phpunit": "^9.5.5", + "scrutinizer/ocular": "^1.8.1", + "unleashedtech/php-coding-standard": "^3.1", + "vimeo/psalm": "^4.7.3" }, - "bin": [ - "bin/commonmark" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "0.16-dev" + "dev-main": "1.2-dev" } }, "autoload": { "psr-4": { - "League\\CommonMark\\": "src/" + "League\\Config\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -304,36 +636,60 @@ "role": "Lead Developer" } ], - "description": "Markdown parser for PHP based on the CommonMark spec", - "homepage": "https://github.com/thephpleague/commonmark", + "description": "Define configuration arrays with strict schemas and access values with dot notation", + "homepage": "https://config.thephpleague.com", "keywords": [ - "commonmark", - "markdown", - "parser" + "array", + "config", + "configuration", + "dot", + "dot-access", + "nested", + "schema" + ], + "support": { + "docs": "https://config.thephpleague.com/", + "issues": "https://github.com/thephpleague/config/issues", + "rss": "https://github.com/thephpleague/config/releases.atom", + "source": "https://github.com/thephpleague/config" + }, + "funding": [ + { + "url": "https://www.colinodell.com/sponsor", + "type": "custom" + }, + { + "url": "https://www.paypal.me/colinpodell/10.00", + "type": "custom" + }, + { + "url": "https://github.com/colinodell", + "type": "github" + } ], - "time": "2016-12-19 00:11:43" + "time": "2022-12-11T20:36:23+00:00" }, { "name": "league/plates", - "version": "3.3.0", + "version": "v3.5.0", "source": { "type": "git", "url": "https://github.com/thephpleague/plates.git", - "reference": "b1684b6f127714497a0ef927ce42c0b44b45a8af" + "reference": "a6a3238e46c6e19af7318fdc36bfbe49b0620231" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/plates/zipball/b1684b6f127714497a0ef927ce42c0b44b45a8af", - "reference": "b1684b6f127714497a0ef927ce42c0b44b45a8af", + "url": "https://api.github.com/repos/thephpleague/plates/zipball/a6a3238e46c6e19af7318fdc36bfbe49b0620231", + "reference": "a6a3238e46c6e19af7318fdc36bfbe49b0620231", "shasum": "" }, "require": { - "php": "^5.3 | ^7.0" + "php": "^7.0|^8.0" }, "require-dev": { - "mikey179/vfsstream": "^1.4", - "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "~1.5" + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "^3.5" }, "type": "library", "extra": { @@ -355,10 +711,15 @@ "name": "Jonathan Reinink", "email": "jonathan@reinink.ca", "role": "Developer" + }, + { + "name": "RJ Garcia", + "email": "ragboyjr@icloud.com", + "role": "Developer" } ], "description": "Plates, the native PHP template system that's fast, easy to use and easy to extend.", - "homepage": "http://platesphp.com", + "homepage": "https://platesphp.com", "keywords": [ "league", "package", @@ -366,76 +727,234 @@ "templating", "views" ], - "time": "2016-12-28 00:14:17" + "support": { + "issues": "https://github.com/thephpleague/plates/issues", + "source": "https://github.com/thephpleague/plates/tree/v3.5.0" + }, + "time": "2023-01-16T20:25:45+00:00" }, { - "name": "myclabs/deep-copy", - "version": "1.6.1", + "name": "nette/schema", + "version": "v1.2.5", "source": { "type": "git", - "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102" + "url": "https://github.com/nette/schema.git", + "reference": "0462f0166e823aad657c9224d0f849ecac1ba10a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/8e6e04167378abf1ddb4d3522d8755c5fd90d102", - "reference": "8e6e04167378abf1ddb4d3522d8755c5fd90d102", + "url": "https://api.github.com/repos/nette/schema/zipball/0462f0166e823aad657c9224d0f849ecac1ba10a", + "reference": "0462f0166e823aad657c9224d0f849ecac1ba10a", "shasum": "" }, "require": { - "php": ">=5.4.0" + "nette/utils": "^2.5.7 || ^3.1.5 || ^4.0", + "php": "7.1 - 8.3" }, "require-dev": { - "doctrine/collections": "1.*", - "phpunit/phpunit": "~4.1" + "nette/tester": "^2.3 || ^2.4", + "phpstan/phpstan-nette": "^1.0", + "tracy/tracy": "^2.7" }, "type": "library", - "autoload": { - "psr-4": { - "DeepCopy\\": "src/DeepCopy/" + "extra": { + "branch-alias": { + "dev-master": "1.2-dev" } }, + "autoload": { + "classmap": [ + "src/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "MIT" + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } ], - "description": "Create deep copies (clones) of your objects", - "homepage": "https://github.com/myclabs/DeepCopy", + "description": "📐 Nette Schema: validating data structures against a given Schema.", + "homepage": "https://nette.org", "keywords": [ - "clone", - "copy", - "duplicate", - "object", - "object graph" + "config", + "nette" ], - "time": "2017-04-12 18:52:22" + "support": { + "issues": "https://github.com/nette/schema/issues", + "source": "https://github.com/nette/schema/tree/v1.2.5" + }, + "time": "2023-10-05T20:37:59+00:00" }, { - "name": "psr/http-message", - "version": "1.0.1", + "name": "nette/utils", + "version": "v3.2.10", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "url": "https://github.com/nette/utils.git", + "reference": "a4175c62652f2300c8017fb7e640f9ccb11648d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/nette/utils/zipball/a4175c62652f2300c8017fb7e640f9ccb11648d2", + "reference": "a4175c62652f2300c8017fb7e640f9ccb11648d2", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=7.2 <8.4" + }, + "conflict": { + "nette/di": "<3.0.6" + }, + "require-dev": { + "jetbrains/phpstorm-attributes": "dev-master", + "nette/tester": "~2.0", + "phpstan/phpstan": "^1.0", + "tracy/tracy": "^2.3" + }, + "suggest": { + "ext-gd": "to use Image", + "ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()", + "ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()", + "ext-json": "to use Nette\\Utils\\Json", + "ext-mbstring": "to use Strings::lower() etc...", + "ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()", + "ext-xml": "to use Strings::length() etc. when mbstring is not available" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "3.2-dev" } }, "autoload": { - "psr-4": { - "Psr\\Http\\Message\\": "src/" + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.", + "homepage": "https://nette.org", + "keywords": [ + "array", + "core", + "datetime", + "images", + "json", + "nette", + "paginator", + "password", + "slugify", + "string", + "unicode", + "utf-8", + "utility", + "validation" + ], + "support": { + "issues": "https://github.com/nette/utils/issues", + "source": "https://github.com/nette/utils/tree/v3.2.10" + }, + "time": "2023-07-30T15:38:18+00:00" + }, + { + "name": "psr/container", + "version": "1.1.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea", + "reference": "513e0666f7216c7459170d56df27dfcefe1689ea", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/1.1.2" + }, + "time": "2021-11-05T16:50:12+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -448,45 +967,204 @@ "homepage": "http://www.php-fig.org/" } ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", "keywords": [ "http", - "http-message", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-factory", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-factory.git", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-factory/zipball/2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "reference": "2b4765fddfe3b508ac62f829e852b1501d3f6e8a", + "shasum": "" + }, + "require": { + "php": ">=7.1", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "PSR-17: Common interfaces for PSR-7 HTTP message factories", + "keywords": [ + "factory", + "http", + "message", "psr", + "psr-17", "psr-7", "request", "response" ], - "time": "2016-08-06 14:39:51" + "support": { + "source": "https://github.com/php-fig/http-factory" + }, + "time": "2024-04-15T12:06:14+00:00" }, { - "name": "psr/log", - "version": "1.0.2", + "name": "psr/http-message", + "version": "2.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.2 || ^8.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -494,62 +1172,802 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "scrivo/highlight.php", + "version": "v9.18.1.10", + "source": { + "type": "git", + "url": "https://github.com/scrivo/highlight.php.git", + "reference": "850f4b44697a2552e892ffe71490ba2733c2fc6e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/scrivo/highlight.php/zipball/850f4b44697a2552e892ffe71490ba2733c2fc6e", + "reference": "850f4b44697a2552e892ffe71490ba2733c2fc6e", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": ">=5.4" + }, + "require-dev": { + "phpunit/phpunit": "^4.8|^5.7", + "sabberworm/php-css-parser": "^8.3", + "symfony/finder": "^2.8|^3.4|^5.4", + "symfony/var-dumper": "^2.8|^3.4|^5.4" + }, + "suggest": { + "ext-mbstring": "Allows highlighting code with unicode characters and supports language with unicode keywords" + }, + "type": "library", + "autoload": { + "files": [ + "HighlightUtilities/functions.php" + ], + "psr-0": { + "Highlight\\": "", + "HighlightUtilities\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Geert Bergman", + "homepage": "http://www.scrivo.org/", + "role": "Project Author" + }, + { + "name": "Vladimir Jimenez", + "homepage": "https://allejo.io", + "role": "Maintainer" + }, + { + "name": "Martin Folkers", + "homepage": "https://twobrain.io", + "role": "Contributor" + } + ], + "description": "Server side syntax highlighter that supports 185 languages. It's a PHP port of highlight.js", + "keywords": [ + "code", + "highlight", + "highlight.js", + "highlight.php", + "syntax" + ], + "support": { + "issues": "https://github.com/scrivo/highlight.php/issues", + "source": "https://github.com/scrivo/highlight.php" + }, + "funding": [ + { + "url": "https://github.com/allejo", + "type": "github" + } + ], + "time": "2022-12-17T21:53:22+00:00" + }, + { + "name": "symfony/console", + "version": "v5.4.47", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", + "reference": "c4ba980ca61a9eb18ee6bcc73f28e475852bb1ed", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php73": "^1.9", + "symfony/polyfill-php80": "^1.16", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.1|^6.0" + }, + "conflict": { + "psr/log": ">=3", + "symfony/dependency-injection": "<4.4", + "symfony/dotenv": "<5.1", + "symfony/event-dispatcher": "<4.4", + "symfony/lock": "<4.4", + "symfony/process": "<4.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0" + }, + "require-dev": { + "psr/log": "^1|^2", + "symfony/config": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/event-dispatcher": "^4.4|^5.0|^6.0", + "symfony/lock": "^4.4|^5.0|^6.0", + "symfony/process": "^4.4|^5.0|^6.0", + "symfony/var-dumper": "^4.4|^5.0|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v5.4.47" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-11-06T11:30:55+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v2.5.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/605389f2a7e5625f273b53960dc46aeaf9c62918", + "reference": "605389f2a7e5625f273b53960dc46aeaf9c62918", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "2.5-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:11:13+00:00" + }, + { + "name": "symfony/http-foundation", + "version": "v5.4.50", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-foundation.git", + "reference": "1a0706e8b8041046052ea2695eb8aeee04f97609" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/1a0706e8b8041046052ea2695eb8aeee04f97609", + "reference": "1a0706e8b8041046052ea2695eb8aeee04f97609", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php80": "^1.16" + }, + "require-dev": { + "predis/predis": "^1.0|^2.0", + "symfony/cache": "^4.4|^5.0|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/expression-language": "^4.4|^5.0|^6.0", + "symfony/http-kernel": "^5.4.12|^6.0.12|^6.1.4", + "symfony/mime": "^4.4|^5.0|^6.0", + "symfony/rate-limiter": "^5.2|^6.0" + }, + "suggest": { + "symfony/mime": "To use the file extension guesser" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpFoundation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Defines an object-oriented layer for the HTTP specification", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/http-foundation/tree/v5.4.50" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-11-03T12:58:48+00:00" + }, + { + "name": "symfony/mime", + "version": "v5.4.45", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "8c1b9b3e5b52981551fc6044539af1d974e39064" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/8c1b9b3e5b52981551fc6044539af1d974e39064", + "reference": "8c1b9b3e5b52981551fc6044539af1d974e39064", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "egulias/email-validator": "~3.0.0", + "phpdocumentor/reflection-docblock": "<3.2.2", + "phpdocumentor/type-resolver": "<1.4.0", + "symfony/mailer": "<4.4", + "symfony/serializer": "<5.4.35|>=6,<6.3.12|>=6.4,<6.4.3" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10|^3.1|^4", + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^4.4|^5.0|^6.0", + "symfony/process": "^5.4|^6.4", + "symfony/property-access": "^4.4|^5.1|^6.0", + "symfony/property-info": "^4.4|^5.1|^6.0", + "symfony/serializer": "^5.4.35|~6.3.12|^6.4.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Allows manipulating MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "support": { + "source": "https://github.com/symfony/mime/tree/v5.4.45" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-10-23T20:18:32+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/a3cc8b044a6ea513310cbd48ef7333b384945638", + "reference": "a3cc8b044a6ea513310cbd48ef7333b384945638", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/380872130d3a5dd3ace2f4010d95125fde5d5c70", + "reference": "380872130d3a5dd3ace2f4010d95125fde5d5c70", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-27T09:58:17+00:00" + }, + { + "name": "symfony/polyfill-intl-icu", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-icu.git", + "reference": "bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c", + "reference": "bfc8fa13dbaf21d69114b0efcd72ab700fb04d0c", + "shasum": "" + }, + "require": { + "php": ">=7.2" + }, + "suggest": { + "ext-intl": "For best performance and support of other locales than \"en\"" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Icu\\": "" + }, + "classmap": [ + "Resources/stubs" + ], + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's ICU-related data and classes", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "icu", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-06-20T22:24:30+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.33.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "reference": "9614ac4d8061dc257ecc64cba1b140873dce8ad3", + "shasum": "" + }, + "require": { + "php": ">=7.2", + "symfony/polyfill-intl-normalizer": "^1.10" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Trevor Rowbotham", + "email": "trevor.rowbotham@pm.me" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", "keywords": [ - "log", - "psr", - "psr-3" + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2016-10-10 12:19:37" + "time": "2024-09-10T14:38:51+00:00" }, { - "name": "symfony/console", - "version": "v3.2.7", + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/console.git", - "reference": "c30243cc51f726812be3551316b109a2f5deaf8d" + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "3833d7255cc303546435cb650316bff708a1c75c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c30243cc51f726812be3551316b109a2f5deaf8d", - "reference": "c30243cc51f726812be3551316b109a2f5deaf8d", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c", + "reference": "3833d7255cc303546435cb650316bff708a1c75c", "shasum": "" }, "require": { - "php": ">=5.5.9", - "symfony/debug": "~2.8|~3.0", - "symfony/polyfill-mbstring": "~1.0" - }, - "require-dev": { - "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/filesystem": "~2.8|~3.0", - "symfony/process": "~2.8|~3.0" + "php": ">=7.2" }, "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/filesystem": "", - "symfony/process": "" + "ext-intl": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "3.2-dev" + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\Console\\": "" + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -558,56 +1976,85 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Console Component", + "description": "Symfony polyfill for intl's Normalizer class and related functions", "homepage": "https://symfony.com", - "time": "2017-04-04 14:33:42" + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/debug", - "version": "v3.2.7", + "name": "symfony/polyfill-mbstring", + "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "56f613406446a4a0a031475cfd0a01751de22659" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/56f613406446a4a0a031475cfd0a01751de22659", - "reference": "56f613406446a4a0a031475cfd0a01751de22659", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { - "php": ">=5.5.9", - "psr/log": "~1.0" + "ext-iconv": "*", + "php": ">=7.2" }, - "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + "provide": { + "ext-mbstring": "*" }, - "require-dev": { - "symfony/class-loader": "~2.8|~3.0", - "symfony/http-kernel": "~2.8|~3.0" + "suggest": { + "ext-mbstring": "For best performance" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "3.2-dev" + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\Debug\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Symfony\\Polyfill\\Mbstring\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -615,47 +2062,79 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Debug Component", + "description": "Symfony polyfill for the Mbstring extension", "homepage": "https://symfony.com", - "time": "2017-03-28 21:38:24" + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-12-23T08:48:59+00:00" }, { - "name": "symfony/finder", - "version": "v3.2.7", + "name": "symfony/polyfill-php73", + "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "b20900ce5ea164cd9314af52725b0bb5a758217a" + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/b20900ce5ea164cd9314af52725b0bb5a758217a", - "reference": "b20900ce5ea164cd9314af52725b0bb5a758217a", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f68c03565dcaaf25a890667542e8bd75fe7e5bb", + "reference": "0f68c03565dcaaf25a890667542e8bd75fe7e5bb", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "3.2-dev" + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Symfony\\Component\\Finder\\": "" + "Symfony\\Polyfill\\Php73\\": "" }, - "exclude-from-classmap": [ - "/Tests/" + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -664,50 +2143,78 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Finder Component", + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", "homepage": "https://symfony.com", - "time": "2017-03-20 09:32:19" + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php73/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-09T11:45:10+00:00" }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.3.0", + "name": "symfony/polyfill-php80", + "version": "v1.33.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", - "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608", + "reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608", "shasum": "" }, "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" + "php": ">=7.2" }, "type": "library", "extra": { - "branch-alias": { - "dev-master": "1.3-dev" + "thanks": { + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, "files": [ "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" ] }, "notification-url": "https://packagist.org/downloads/", @@ -715,6 +2222,10 @@ "MIT" ], "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, { "name": "Nicolas Grekas", "email": "p@tchwork.com" @@ -724,40 +2235,56 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill for the Mbstring extension", + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", - "mbstring", "polyfill", "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-01-02T08:10:11+00:00" }, { "name": "symfony/process", - "version": "v3.2.7", + "version": "v5.4.51", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "57fdaa55827ae14d617550ebe71a820f0a5e2282" + "reference": "467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/57fdaa55827ae14d617550ebe71a820f0a5e2282", - "reference": "57fdaa55827ae14d617550ebe71a820f0a5e2282", + "url": "https://api.github.com/repos/symfony/process/zipball/467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f", + "reference": "467bfc56f18f5ef6d5ccb09324d7e988c1c0a98f", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": ">=7.2.5", + "symfony/polyfill-php80": "^1.16" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.2-dev" - } - }, "autoload": { "psr-4": { "Symfony\\Component\\Process\\": "" @@ -780,46 +2307,70 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Process Component", + "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", - "time": "2017-03-27 18:07:02" + "support": { + "source": "https://github.com/symfony/process/tree/v5.4.51" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://github.com/nicolas-grekas", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2026-01-26T15:53:37+00:00" }, { - "name": "symfony/yaml", - "version": "v3.2.7", + "name": "symfony/service-contracts", + "version": "v2.5.4", "source": { "type": "git", - "url": "https://github.com/symfony/yaml.git", - "reference": "62b4cdb99d52cb1ff253c465eb1532a80cebb621" + "url": "https://github.com/symfony/service-contracts.git", + "reference": "f37b419f7aea2e9abf10abd261832cace12e3300" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/62b4cdb99d52cb1ff253c465eb1532a80cebb621", - "reference": "62b4cdb99d52cb1ff253c465eb1532a80cebb621", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f37b419f7aea2e9abf10abd261832cace12e3300", + "reference": "f37b419f7aea2e9abf10abd261832cace12e3300", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": ">=7.2.5", + "psr/container": "^1.1", + "symfony/deprecation-contracts": "^2.1|^3" }, - "require-dev": { - "symfony/console": "~2.8|~3.0" + "conflict": { + "ext-psr": "<1.1|>=2" }, "suggest": { - "symfony/console": "For validating YAML files using the lint command" + "symfony/service-implementation": "" }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { - "dev-master": "3.2-dev" + "dev-main": "2.5-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Yaml\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Symfony\\Contracts\\Service\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -827,52 +2378,85 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Yaml Component", + "description": "Generic abstractions related to writing services", "homepage": "https://symfony.com", - "time": "2017-03-20 09:45:15" + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v2.5.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-09-25T14:11:13+00:00" }, { - "name": "webuni/commonmark-table-extension", - "version": "0.6.1", + "name": "symfony/string", + "version": "v5.4.47", "source": { "type": "git", - "url": "https://github.com/webuni/commonmark-table-extension.git", - "reference": "ebbd69b63436283ec726658835b213ec634485e8" + "url": "https://github.com/symfony/string.git", + "reference": "136ca7d72f72b599f2631aca474a4f8e26719799" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webuni/commonmark-table-extension/zipball/ebbd69b63436283ec726658835b213ec634485e8", - "reference": "ebbd69b63436283ec726658835b213ec634485e8", + "url": "https://api.github.com/repos/symfony/string/zipball/136ca7d72f72b599f2631aca474a4f8e26719799", + "reference": "136ca7d72f72b599f2631aca474a4f8e26719799", "shasum": "" }, "require": { - "league/commonmark": "^0.14|^0.15", - "php": "^5.5|^7.0" + "php": ">=7.2.5", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php80": "~1.15" + }, + "conflict": { + "symfony/translation-contracts": ">=3.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^1.9", - "phpunit/phpunit": "^4.3|^5.0", - "sllh/php-cs-fixer-styleci-bridge": "^2.0", - "symfony/var-dumper": "^2.7|^3.0" + "symfony/error-handler": "^4.4|^5.0|^6.0", + "symfony/http-client": "^4.4|^5.0|^6.0", + "symfony/translation-contracts": "^1.1|^2", + "symfony/var-exporter": "^4.4|^5.0|^6.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "0.7-dev" - } - }, "autoload": { + "files": [ + "Resources/functions.php" + ], "psr-4": { - "Webuni\\CommonMark\\TableExtension\\": "src" - } + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -880,66 +2464,82 @@ ], "authors": [ { - "name": "Martin Hasoň", - "email": "martin.hason@gmail.com", - "role": "Lead Developer" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { - "name": "Webuni s.r.o.", - "homepage": "https://www.webuni.cz" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "The table extension for CommonMark PHP implementation", - "homepage": "https://github.com/webuni/commonmark-table-extension", + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", "keywords": [ - "commonmark", - "markdown", - "table" + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v5.4.47" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2017-01-11 14:52:17" + "time": "2024-11-10T20:33:58+00:00" }, { - "name": "webuni/front-matter", - "version": "1.0.0", + "name": "symfony/yaml", + "version": "v5.4.45", "source": { "type": "git", - "url": "https://github.com/webuni/front-matter.git", - "reference": "2c655c21e327e50708a847c5c6a4b52f1a111fdb" + "url": "https://github.com/symfony/yaml.git", + "reference": "a454d47278cc16a5db371fe73ae66a78a633371e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webuni/front-matter/zipball/2c655c21e327e50708a847c5c6a4b52f1a111fdb", - "reference": "2c655c21e327e50708a847c5c6a4b52f1a111fdb", + "url": "https://api.github.com/repos/symfony/yaml/zipball/a454d47278cc16a5db371fe73ae66a78a633371e", + "reference": "a454d47278cc16a5db371fe73ae66a78a633371e", "shasum": "" }, "require": { - "php": "^5.6|^7.0", - "symfony/yaml": "^2.3|^3.0" + "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<5.3" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^1.9", - "mthaml/mthaml": "^1.2", - "nette/neon": "^2.2", - "phpunit/phpunit": "^5.4", - "sllh/php-cs-fixer-styleci-bridge": "^2.0", - "symfony/var-dumper": "^3.0", - "twig/twig": "^1.27|^2.0", - "yosymfony/toml": "~0.3" + "symfony/console": "^5.3|^6.0" }, "suggest": { - "nette/neon": "If you want to use NEON as front matter", - "yosymfony/toml": "If you want to use TOML as front matter" + "symfony/console": "For validating YAML files using the lint command" }, + "bin": [ + "Resources/bin/yaml-lint" + ], "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, "autoload": { "psr-4": { - "Webuni\\FrontMatter\\": "src" - } + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -947,34 +2547,46 @@ ], "authors": [ { - "name": "Martin Hasoň", - "email": "martin.hason@gmail.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Webuni s.r.o.", - "homepage": "https://www.webuni.cz" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Front matter parser and dumper for PHP", - "homepage": "https://github.com/webuni/front-matter", - "keywords": [ - "front-matter", - "json", - "neon", - "toml", - "yaml" + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v5.4.45" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } ], - "time": "2016-12-30 14:37:21" + "time": "2024-09-25T14:11:13+00:00" } ], "packages-dev": [], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "justinwalsh/daux.io": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": [], - "platform-dev": [] + "platform-dev": [], + "platform-overrides": { + "php": "7.4" + }, + "plugin-api-version": "2.6.0" } diff --git a/en/01_Agenda/v1/01_Installation.md b/en/01_Agenda/v1/01_Installation.md new file mode 100755 index 00000000..c795e9ad --- /dev/null +++ b/en/01_Agenda/v1/01_Installation.md @@ -0,0 +1,24 @@ +The MODX installer should install the package automatically from the modmore +repository. + +A custom manager page called _Agenda_ is installed within the _Extras_ menu. +Also, some [snippets](04_Snippets/index.md) in the element category named +_Agenda_ are created. + +There are some system settings available in the namespace _agenda_. These can +also be edited in the [settings](02_Custom_Manager_Page/08_Settings.md) (cog +icon) tab of the _Agenda_ custom manager page. + +If you want to connect events, categories, calendars or locations to MODX +resources, you have to enter the parents of those resources in the system +settings. + +To use the map and the geolocation option in the location address tab, you have +to enter a [Google Maps API +Key](https://developers.google.com/maps/documentation/javascript/get-api-key) in +the Agenda [system setting](02_Custom_Manager_Page/08_Settings.md) +`agenda.google_maps_api_key`. You have to activate the Maps JavaScript API and +the Geocoding API in the created Google Cloud Platform project. + +After the installation you have to set up a cronjob, if you want to use more than +100 repeats of a repeating event or if you want to set up feeds. diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/01_Overview.md b/en/01_Agenda/v1/02_Custom_Manager_Page/01_Overview.md new file mode 100755 index 00000000..b417a6ee --- /dev/null +++ b/en/01_Agenda/v1/02_Custom_Manager_Page/01_Overview.md @@ -0,0 +1,107 @@ +This tab contains a calendar view of the current month. + +![Tab Overview](img/overview.png) + +You can create a new event with a click on the plus sign at beneath the day +number in the month view (or the date/weekday in the week/day view). There is +also a create event button on the top left of the tab. + +The calendar can be filtered by calendar or category dropdown selects and by a +search input on the top right of the tab. It can also be filtered by the +publication status of an event. + +The arrow buttons on the top left can be used to switch the event month (in +the month view). If you click on today, the calendar will show the current day +in the selected view. + +The view mode can be changed on top right to the month view, the week view, +the day view and the list view. + +Each event can be edited by a click on the edit icon displayed on an event. It +can be deleted after a confirmation with a click on the trash icon. + +There is also a hover popup for each event, that shows a short information for +the hovered event. + +![Overview Hover](img/overview-hover.png) + +## Create/Edit + +The create/edit window for one event has a lot of options, that can be set. + +![Update Event](img/event-edit.png) + +### Event Tab + +In the event tab you have to set the event title and the event calendar, where +the event is shown in. An event must have a start date/time and an end +date/time, and it can have a location. The location can be created/edited +directly on the event tab. + +The event can be linked with a MODX resource. This combo field is only shown, +when the system setting `agenda.parents_event` is filled with a comma separated +list of resources, that are parents for the resources selectable with the combo +field. This combo has a select, a preview and a quickedit button. The resource +can be edited in a new window with an alt click on the quickedit button. + +The event could be restricted to a context, it has to be tagged with at least +one category, and it could be toggled to inactive. If the `All Day Event` +checkbox is checked, the events don't have a time input. + +If the event is set as repeating event, an additional section is visible. There +you could set the repeating type. On base of the repeating type, you have +different inputs visible. + +With the interval the event repeats could be restricted to every `X` +days/months/weeks/years. The repeats will be calculated until the date set in +the last occurence input. There is a maximum of 100 repeating events that are +generated during saving an event. This maximum could be changed with the +optional createable `agenda.repeating_max_occurance` system setting. With the +`weekly` repeating type, you could set the weekdays, where the event will start. +The start date/time will then be recalculated on base of the first repeating +event. With the `monthly by weekday` repeating type, you could set the event +i.e. to the second wednesday or last tuesday of a month. With the `custom` +repeating type, you can create your own event dates in the repeats grid. + +The fields on the event tab can be extended by the [Extended Event +Fields](../06_Extended_Fields.md) system setting. + +### Repeats Tab + +In the repeats tab you could view the repeats of the current event. You could +edit and delete each repeat. If the repeat type is `custom` you can add your own +event dates. The title column of a repeat is light gray, when is uses the +default title. When one field of the repeat does not use the default value, the +modified column contains a green tick. + +The grid can be toggled to show past/future repeats. It also can be filtered by +a search input on the top right above the repeats grid. + +During editing a repeat, you can change the repeat dates, the title and the +description for each repeat. + +The fields in the repeat edit window can be extended by the [Extended Repeat +Fields](../06_Extended_Fields.md) system setting. + +The repeats are marked to be reset, when the repeat options of an event are +changed or the event dates are modified. When all repeating events will be +changed or removed during saving the event a warning will be shown. + +### Description/Content Tab + +In the description tab you could set the description for the current event. In +the content tab you could set the content for the current event. The editor type +of the content/description input could be set with the `agenda.editor_type` +system setting to htmleditor (the system-wide richtext editor), modx-texteditor +(the system-wide code editor) or textarea. + +### Images/Videos Tab + +After an event is saved, you could attach images and videos to the saved event +in the images/videos tab. Each image/video could have a title and a description. +It could also be toggled to inactive. + +### User Tab + +In the user tab you could restrict the event to multiple users and/or multiple +usergroups. diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/02_Events.md b/en/01_Agenda/v1/02_Custom_Manager_Page/02_Events.md new file mode 100755 index 00000000..b29a5527 --- /dev/null +++ b/en/01_Agenda/v1/02_Custom_Manager_Page/02_Events.md @@ -0,0 +1,36 @@ +This tab contains a paginated grid with all future (or past) events. + +![Tab Events](img/events.png) + +You can create a new event with a click on the create event button on the top +left above the events grid. + +If the manger user has `agenda_export` or `agend_import` permissions an export +and import button is displayed right of the create event button. This allows the +user to [export and import](../07_Export_Import_Events.md) the events. + +The grid can be toggled to show past or future events. When the grid shows past +events, the toggle button is shown in red. It can be filtered by calendar and +filtered by category. It can also be filtered by the publication status of an +event and its recurrences. In addition, it can be filtered by a search entry at +the top right above the event grid. + +Each event can be edited by clicking on the edit icon in the event's row. It can +be duplicated by clicking on the duplicate icon in the row of the event. It can +be deleted after confirmation by clicking on the trash icon in the row of the +event. + +The row of each event shows the event source, the title, the calendar, the +categories, the start and the end date and the active state of an entry. The +title can be edited inline with a double click on the text. An event would +normally have a `Local` source. If the event is created by a feed it will have a +`Feed` source. + +If the [extended event fields](../06_Extended_Fields.md) are set, the columns of +those extended fields are shown after the `active` column. + +## Create/Edit + +The create/edit window for one event has a lot of options, that can be set. The +information about those options can be found in the [Tab +Overview](01_Overview.md#createedit) documentation. diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/03_Categories.md b/en/01_Agenda/v1/02_Custom_Manager_Page/03_Categories.md new file mode 100755 index 00000000..7581cb19 --- /dev/null +++ b/en/01_Agenda/v1/02_Custom_Manager_Page/03_Categories.md @@ -0,0 +1,36 @@ +This tab contains a paginated grid with all categories. + +![Tab Categories](img/categories.png) + +You can create a new category with a click on the create category button on the top +left above the categories grid. + +The grid can be filtered by a search input on the top right above the +categories grid. + +Each category can be edited by a click on the edit icon in the row of the +category. And it can be deleted after a confirmation with a click on the trash +icon in the row of the category. + +The row of each category shows the color icon, the name, the alias and the +active state of an entry. The name and the alias can be edited inline with +a double click on the text. + +## Create/Edit + +The create/edit window for one category has some options, that can be set. + +![Update Category](img/category-edit.png) + +You can set the category name, the category alias, and you can toggle it to +inactive. And you can set the category text and background color with a color +picker. + +The category can be linked with a MODX resource. This combo field is only +shown, when the system setting `agenda.parents_category` is filled with a comma +separated list of resources, that are parents for the resources selectable with +the combo field. This combo has a select, a preview and a quickedit button. The +resource can be edited in a new window with an alt click on the quickedit +button. + +![Update Category Colorpicker](img/category-colorpicker.png) diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/04_Calendars.md b/en/01_Agenda/v1/02_Custom_Manager_Page/04_Calendars.md new file mode 100755 index 00000000..55a48e59 --- /dev/null +++ b/en/01_Agenda/v1/02_Custom_Manager_Page/04_Calendars.md @@ -0,0 +1,35 @@ +This tab contains a paginated grid with all calendars. + +![Tab Calendars](img/calendars.png) + +You can create a new calendar with a click on the create calendar button on the top +left above the calendars grid. + +The grid can be filtered by a search input on the top right above the +calendars grid. + +Each calendar can be edited by a click on the edit icon in the row of the +calendar. And it can be deleted after a confirmation with a click on the trash +icon in the row of the calendar. + +The row of each calendar shows the color icon, the name, the alias and the +active state of an entry. The name and the alias can be edited inline with +a double click on the text. + +## Create/Edit + +The create/edit window for one calendar has some options, that can be set. + +![Update Calendar](img/calendar-edit.png) + +You can set the calendar name, and you can toggle it to inactive. And you +can set the calendar text and background color with a color picker. + +The calendar can be linked with a MODX resource. This combo field is only +shown, when the system setting `agenda.parents_calendar` is filled with a comma +separated list of resources, that are parents for the resources selectable with +the combo field. This combo has a select, a preview and a quickedit button. The +resource can be edited in a new window with an alt click on the quickedit +button. + +![Update Calendar Colorpicker](img/calendar-colorpicker.png) diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/05_Locations.md b/en/01_Agenda/v1/02_Custom_Manager_Page/05_Locations.md new file mode 100755 index 00000000..707e2879 --- /dev/null +++ b/en/01_Agenda/v1/02_Custom_Manager_Page/05_Locations.md @@ -0,0 +1,45 @@ +This tab contains a paginated grid with all locations. + +![Tab Locations](img/locations.png) + +You can create a new location with a click on the create location button on the top +left above the locations grid. + +The grid can be filtered by a search input on the top right above the +locations grid. + +Each location can be edited by a click on the edit icon in the row of the +location. And it can be deleted after a confirmation with a click on the trash +icon in the row of the location. + +The row of each location shows the name, the formatted address, the active state +and the show on map setting (if you have set the Google Maps API key in the +system settings) of an entry. The name and the address can be edited inline +with a double click on the text. + +## Create/Edit + +The create/edit window for one location has some options, that can be set. + +![Update Location](img/location-edit-location.png) + +### Location Tab + +On the location tab you can set the location name, toggle it to inactive (and +toggle the display on a map, if you have set the Google Maps API key in the +system settings). + +The fields on the location tab can be extended by the [Extended Repeat +Fields](../06_Extended_Fields.md) system setting. + +![Update Location Address](img/location-edit-address.png) + +### Address Tab + +On the address tab you can enter the address. If you have set the Google Maps +API key in the system settings, you can geocode that address with the search +button on the map. If marker on the map is not set right, you can drag it +around (the location latitude and longitude values will be changed). Also, the +map content can be dragged with the mouse (the map latitude and longitude +values will be changed). The zoom level of the map can be changed by clicking +on the plus/minus signs (the zoom value will be changed). diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/06_Feeds.md b/en/01_Agenda/v1/02_Custom_Manager_Page/06_Feeds.md new file mode 100755 index 00000000..91dd7842 --- /dev/null +++ b/en/01_Agenda/v1/02_Custom_Manager_Page/06_Feeds.md @@ -0,0 +1,34 @@ +This tab contains a paginated grid with all feeds. + +![Tab Feeds](img/feeds.png) + +You can create a new feed with a click on the create feed button on the top +left above the feeds grid. + +The grid can be filtered by a search input on the top right above the +feeds grid. + +Each feed can be edited by a click on the edit icon in the row of the feed. And +it can be deleted after a confirmation with a click on the trash icon in the row +of the feed. The feed can be refreshed with a click on the refresh icon. + +The row of each feed shows the feed url, date/time of the last run and the +next run by the cronjob, the feed type the calendar, the categories and the +active state of an entry. The feed url and the feed type can be edited inline +with a double click on the text. + +## Create/Edit + +The create/edit window for one feed has some options, that can be set. + +![Update Feed](img/feed-edit.png) + +You can set the feed URL the events are retrieved from. You can select the +calendar, where the feed events are imported into. You can set the categories, +the feed events will get. You can set the update interval and frequency for +the cronjob update of the feed. You can set the feed type (iCal or XML) and +you can toggle the feed to inactive. + +The cronjob URL can't use the webcal protocol. Please try to change the url from +`webcal://calendar.domain/url.path` to `https://calendar.domain/url.path` in +that case. diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/07_Modules.md b/en/01_Agenda/v1/02_Custom_Manager_Page/07_Modules.md new file mode 100755 index 00000000..78d6bf1a --- /dev/null +++ b/en/01_Agenda/v1/02_Custom_Manager_Page/07_Modules.md @@ -0,0 +1,12 @@ +This tab contains a paginated grid with all modules installed in Agenda. + +![Tab Modules](img/modules.png) + +It is visible only to a user who has enabled the `agenda_modules` permission. A +module can be added by entering a package name in lowercase. An installed module +can be activated, deactivated and removed with one click in the context menu of +the module row. The `active` column ‘Active’ can be edited inline and the trash +icon can remove a module. At least the modules can be sorted by drag & drop. + +The creation of custom modules will be described later. Until then, we will +send the code of a skeleton module on demand. diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/08_Settings.md b/en/01_Agenda/v1/02_Custom_Manager_Page/08_Settings.md new file mode 100755 index 00000000..28dd3a9f --- /dev/null +++ b/en/01_Agenda/v1/02_Custom_Manager_Page/08_Settings.md @@ -0,0 +1,7 @@ +This tab contains a paginated grid with all settings of the agenda namespace. + +![Tab Settings](img/settings.png) + +It is only visible for a user that has the `setting` or the `agenda_settings` +permission enabled. Each setting can be edited the same as in the MODX system +settings panel. diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/calendar-colorpicker.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/calendar-colorpicker.png new file mode 100644 index 00000000..e9a9ab49 Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/calendar-colorpicker.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/calendar-edit.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/calendar-edit.png new file mode 100644 index 00000000..8614d0b2 Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/calendar-edit.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/calendars.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/calendars.png new file mode 100644 index 00000000..7394b57d Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/calendars.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/categories.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/categories.png new file mode 100644 index 00000000..fae150c8 Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/categories.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/category-colorpicker.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/category-colorpicker.png new file mode 100644 index 00000000..4fda9f44 Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/category-colorpicker.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/category-edit.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/category-edit.png new file mode 100644 index 00000000..9d1765e1 Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/category-edit.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/event-edit.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/event-edit.png new file mode 100644 index 00000000..56480361 Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/event-edit.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/events.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/events.png new file mode 100644 index 00000000..8af0ace7 Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/events.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/feed-edit.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/feed-edit.png new file mode 100644 index 00000000..24bee67f Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/feed-edit.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/feeds.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/feeds.png new file mode 100644 index 00000000..0878db82 Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/feeds.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/location-edit-address.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/location-edit-address.png new file mode 100644 index 00000000..91d9a0fe Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/location-edit-address.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/location-edit-location.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/location-edit-location.png new file mode 100644 index 00000000..99ed6e1e Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/location-edit-location.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/locations.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/locations.png new file mode 100644 index 00000000..dc1d18fc Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/locations.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/modules.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/modules.png new file mode 100644 index 00000000..36284803 Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/modules.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/overview-hover.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/overview-hover.png new file mode 100644 index 00000000..90bc953e Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/overview-hover.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/overview.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/overview.png new file mode 100644 index 00000000..25882500 Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/overview.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/img/settings.png b/en/01_Agenda/v1/02_Custom_Manager_Page/img/settings.png new file mode 100644 index 00000000..e4c0bdf4 Binary files /dev/null and b/en/01_Agenda/v1/02_Custom_Manager_Page/img/settings.png differ diff --git a/en/01_Agenda/v1/02_Custom_Manager_Page/index.md b/en/01_Agenda/v1/02_Custom_Manager_Page/index.md new file mode 100755 index 00000000..9fcfa653 --- /dev/null +++ b/en/01_Agenda/v1/02_Custom_Manager_Page/index.md @@ -0,0 +1,35 @@ +You can create and edit your event data on the custom manager page of _Agenda_. +This page contains up to eight tabs where you can manage different parts of the +events. + +#### Overview + +This tab contains a calendar [overview](01_Overview.md) of the current month. + +#### Events + +This tab contains a grid view of all [events](02_Events.md). + +#### Categories + +This tab contains a grid view of all [categories](03_Categories.md). + +#### Calendars + +This tab contains a grid view of all [calendars](04_Calendars.md). + +#### Locations + +This tab contains a grid view of all [locations](05_Locations.md). + +#### Feeds + +This tab contains a grid view of all [feeds](06_Feeds.md). + +#### Modules (puzzle icon) + +This tab contains a grid view of all [modules](07_Modules.md). + +#### Settings (cog icon) + +This tab contains a grid view of all [settings](08_Settings.md). diff --git a/en/01_Agenda/v1/03_System_Settings.md b/en/01_Agenda/v1/03_System_Settings.md new file mode 100755 index 00000000..86a76bf5 --- /dev/null +++ b/en/01_Agenda/v1/03_System_Settings.md @@ -0,0 +1,53 @@ +_Agenda_ contains some _system settings_ in the `agenda` namespace. + +These are available in the MODX system settings panel and in the +[settings](02_Custom_Manager_Page/08_Settings.md) tab (cog icon) of the _Agenda_ +custom manager page. + +| Key | Name | Description | Default | +|---------------------------------|----------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------| +| agenda.blur_data | Blur Data | ** Since 1.5.6 ** Blur data to present the functionality without revealing personal data. | No | +| agenda.category_required | Category Required | An event requires a category. | Yes | +| agenda.cronjob_id | Cronjob ID | String, that has to be added to the cronjob url as cronjob_id parameter. | - | +| agenda.debug | Debug | Log debug information in the MODX error log. | No | +| agenda.default_timezone | Default Timezone | Default [time zone](https://www.php.net/manual/en/timezones.php) for events. | Europe/Berlin | +| agenda.detail_id | Detail ID | ID of a resource containing AgendaDetail snippet call. | - | +| agenda.editor_type | Editor Type | Editor type for text fields (htmleditor, modx-texteditor or textarea). | htmleditor | +| agenda.extended_event_fields | Extended Event Fields | JSON encoded array of extended event fields. | - | +| agenda.extended_location_fields | Extended Location Fields | ** Since 1.4.0 ** JSON encoded array of extended location fields. | - | +| agenda.extended_repeat_fields | Extended Repeat Fields | ** Since 1.4.0 ** JSON encoded array of extended repeat fields. | - | +| agenda.extended_xtypes_script | Extended xtypes Script | ** Since 1.4.0 ** Url to a script, that defines custom xtypes. Relative to the manager url or (if absolute) to the base url. | - | +| agenda.google_maps_api_key | Google Maps API Key | [Request](https://developers.google.com/maps/documentation/javascript/get-api-key) a Google Maps API Key. | - | +| agenda.google_maps_default_lat | Google Maps Default Latitude | Default latitude for the displayed map when creating/editing a location. | 51.977825 | +| agenda.google_maps_default_lng | Google Maps Default Longitude | Default longitude for the displayed map when creating/editing a location. | 7.291066 | +| agenda.google_maps_default_zoom | Google Maps Standard Zoom | Default zoom for the displayed map when creating/editing a location. | 9 | +| agenda.google_maps_region | Google Maps API Preferred Region | [Preferred region](https://developers.google.com/maps/documentation/javascript/geocoding#GeocodingRegionCodes) for the geocoding result. | - | +| agenda.image_mediasource | Image Media Source | Media source for event images. | 1 | +| agenda.import_export_type | Import/Export Type | ** Since 1.5.0 ** File type of the imported/exported files. Can be set to 'csv', 'excel', 'yaml' | csv | +| agenda.list_id | List ID | ID of a resource containing an AgendaList snippet call. | - | +| agenda.locale | Locale | Set the locale for Agenda. Leave blank to use the MODX system setting 'locale'. See [the PHP documentation](https://www.php.net/setlocale) for more information. | - | +| agenda.manager_date_alt_formats | Date Alt Formats | ** Since 1.4.0 ** Multiple date formats separated by "|" that are tried when a user input value is parsed and it does not match the defined format. Each format must be valid according to [Ext JS Date](https://docs.sencha.com/extjs/3.4.0/#!/api/Date). | (lexicon) | +| agenda.manager_date_format | Date Format | The format must be valid according to [Ext JS Date](https://docs.sencha.com/extjs/3.4.0/#!/api/Date). | (lexicon) | +| agenda.manager_date_format_long | Date Format (long) | The format must be valid according to [Ext JS Date](https://docs.sencha.com/extjs/3.4.0/#!/api/Date). | (lexicon) | +| agenda.manager_time_format | Time Format | The format must be valid according to [Ext JS Date](https://docs.sencha.com/extjs/3.4.0/#!/api/Date). | (lexicon) | +| agenda.manager_time_increment | Time Steps | Number of minutes between individual time values in the time selection field. | 15 | +| agenda.parents_calendar | Calendar Parent Resources | Comma-separated list of parent resources to select a resource connected with a calendar. | - | +| agenda.parents_category | Category Parent Resources | Comma-separated list of parent resources to select a resource connected with a category. | - | +| agenda.parents_event | Event Parent Resources | Comma separated list of parent resources to select a resource connected with an event. | - | +| agenda.parents_location | Location Parent Resources | Comma separated list of parent resources to select a resource connected with a location. | - | +| agenda.repeating_max_occurance | Maximum Occurance | Maximum orccurance of repeating events. | 100 | +| agenda.show_ids | Show ID Columns | ** Since 1.5.5 ** Show ID columns in the tables. | No | +| agenda.use_activate_at | Use Activate | ** Since 1.6.0 ** Show the ‘Activate/Deactivate At’ input in the event, the repeat, the location, the image, the video, the category and the calendar edit window. The data will be activated/deactivated during a page request. | No | +| agenda.use_category | Use Category | Show the category input in the events editing window. Show the categories column in the events grid. Show the categories tab in the Agenda custom manager page. | Yes | +| agenda.use_content | Use Event Content | ** Since 1.6.3 ** Show the content tab in the event edit window. | Yes | +| agenda.use_context | Use Contexts | Show the context input in the event edit window. | Yes | +| agenda.use_images | Use Event Images | ** Since 1.6.3 ** Show the images tab in the event edit window. | Yes | +| agenda.use_location | Use Location | Show the location input in the event edit window. Show the locations tab in the Agenda custom manager page. | Yes | +| agenda.use_users | Use Event Users | ** Since 1.6.3 ** Show the users tab in the event edit window. | Yes | +| agenda.use_videos | Use Event Videos | ** Since 1.6.3 ** Show the videos tab in the event edit window. | Yes | +| agenda.video_mediasource | Video Media Source | Media Source for Event Videos. | 1 | + +The settings `agenda.extended_event_fields`, `agenda.extended_repeat_fields` and +`agenda.extended_location_fields` can use `@FILE` or `@CHUNK` bindings. Path +placeholders like `{core_path}`, `{base_path}` and `{assets_path}` can be used. +All paths have to stay inside the MODX base path because of security reasons. diff --git a/en/01_Agenda/v1/04_Snippets/01_AgendaList.md b/en/01_Agenda/v1/04_Snippets/01_AgendaList.md new file mode 100755 index 00000000..8267d6f6 --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/01_AgendaList.md @@ -0,0 +1,162 @@ +This snippet displays events in a list view. + +## Properties + +It uses the following snippet properties: + +| Property | Description | Default | +|--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------| +| active | **Since 1.6.3** If this option is disabled, the active status of an event is not regarded. | 1 (Yes) | +| ajax | **Since 1.4.0** If set, the snippet output will be directly returned to the browser as a JSON result when the page is requested with the same value in the ajax request parameter. | 0 (No) | +| allowedRequestKeys | Comma-separated list of request keys, that can be used to filter the displayed events. Defaults to all allowed. | - | +| calendars | Comma-separated list of aliases of calendars to filter the displayed events. | - | +| categories | Comma separated list of aliases of categories to filter the displayed events. | - | +| categoryTpl | Name of a chunk that contains the template of one category in the category list of an event. | tplAgendaEventCategory | +| contexts | Comma separated list of context keys to filter the displayed events. | - | +| daterangeFormat | Format of the daterange displayed in an event. | - | +| daterangeSeparator | Separator in the daterange displayed in an event. | - | +| detailId | ID of a resource containing an AgendaDetail snippet call. | - | +| durationParts | Number of detail parts of the event duration output. | 1 | +| durationRound | **Since 1.5.0** Rounding type for event duration. | ceil | +| emptyTpl | Name of a chunk that contains the template for an empty list of events. | tplAgendaEventEmpty | +| end | The end date to filter the displayed events. Must contain a [supported date and time format](https://www.php.net/manual/de/datetime.formats.php). | today +1 month 0:00 | +| events | Comma separated list of event IDs to filter the displayed events and their repeats. Supersedes the repeats property. | - | +| excludeEvents | Comma separated list of event IDs to exclude from the displayed events. | - | +| excludeRepeats | Comma separated list of repeating event IDs to exclude from the displayed events. | - | +| groupby | **Since 1.5.0** xPDO group by clause to filter the events. | - | +| imageTpl | Name of a chunk that contains the template for one image in the image list of an event. | tplAgendaEventImage | +| limit | Limit the number of events in the result. Use "0" for unlimited events. | 20 | +| listId | ID of a resource containing an AgendaList snippet call. | - | +| locale | The locale for the displayed formatted date. Defaults to the current system/context locale setting. | - | +| locations | Comma separated list of aliases of locations to filter the displayed events. | - | +| locationTpl | Name of a chunk that contains the template for the location of an event. | tplAgendaEventLocation | +| offset | The offset of events to skip. | - | +| outputSeparator | An optional string to separate each tpl instance. | - | +| repeats | Comma separated list of repeating event IDs to filter the displayed repeating events. Overridden by the events property. | - | +| resourceTpl | Name of a chunk that contains the template for the linked resource of an event. | - | +| sortby | Sort field for sorting the output. It could also contain a JSON object to sort the ouput by multiple fields like
{"AgendaEvents.title":"ASC","all_startdate":"ASC"}
. | all_startdate | +| sortdir | Sort direction for sorting the output. Unused when the sortby property contains a valid JSON object. | ASC | +| start | The start date to filter the displayed events. Must contain a [supported date and time format](https://www.php.net/manual/de/datetime.formats.php). | today 0:00 | +| toPlaceholder | If set, the snippet result will be assigned to this placeholder instead of outputting it directly. | - | +| totalVar | The key of a placeholder that indicates the total number of events. | agendalist.total | +| tpl | Name of a chunk that contains the template for one event. | tplAgendaEventRow | +| usergroups | Comma separated list of user group names to filter the displayed events. | - | +| users | Comma separated list of user IDs to filter the displayed events. | - | +| videoTpl | Name of a chunk that contains the template for one video in the video list of an event. | tplAgendaEventVideo | +| where | **Since 1.5.0** JSON encoded xPDO where clause to filter the displayed events. | - | +| wrapperTpl | Name of a chunk that contains the wrapper template for all events. | tplAgendaEventWrapper | + +## Placeholders + +The following placeholders are available in the different (default) chunks. Each +snippet property will be set as placeholder in each template chunk, i.e. a +snippet call ```[[!AgendaDetail? &subtitle=`whatever`]]``` will fill the +placeholder subtitle in each used chunk with the value `whatever`. + +**CAUTION:** The default template chunks for both snippets are overwritten +during each package update, so please rename the chunks before editing them. + +### tplAgendaEventRow + +| Placeholder | Description | +|---------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| allday | Contains 1 if the event is an all day event (otherwise 0). | +| calendar_background | The background color of the calendar of the event. | +| calendar_foreground | The foreground color of the calendar of the event. | +| calendar_name | The calendar name. | +| categories | All categories of the event formatted by the chunk set with the categoryTpl property | +| description | The description of the event. | +| detail_url | The url that shows the event detail. Will be generated with the system/context setting `agenda.detail_id`. This resource should contain an AgendaDetail snippet call. | +| duration | The formatted duration of the event. The details of the duration could be set with the `durationParts` snippet property. | +| enddate | The start date of the event formatted in ISO 8601 (could be formatted i.e. with ```[[+enddate:strtotime:date=`%a. %d.%m.%Y`]]```). | +| idx | The number of the event starting with 1. | +| images | All images of the event formatted by the chunk set with the imageTpl property | +| imageurls | An array of all image urls. The placeholder `[[+imageurls.1]]` contains the url of the first image | +| location | The location of the event formatted by the chunk set with the locationTpl property | +| range | The formatted date range of the event. The format is defined with the lexicon entries `agenda.php_format_daterange` and `agenda.php_format_separator` and could be overridden by the `daterangeFormat` snippet property. The [format rules](#range-placeholder-format) are described below. | +| repeating | Contains 1 if the event is an repeating event (otherwise 0). | +| resource_id | The id of a linked resource of the event. | +| startdate | The start date of the event formatted in ISO 8601 (could be formatted i.e. with ```[[+startdate:strtotime:date=`%a. %d.%m.%Y`]]```). | +| title | The title of the event. | +| videos | All videos of the event formatted by the chunk set with the videosTpl property | +| videourls | An array of all video urls. The placeholder `[[+videourls.1]]` contains the url of the first video | + +[Extended fields](../06_Extended_Fields) are available as placeholder with the prefix `extended` in the +event row template. + +### tplAgendaEventWrapper + +| Placeholder | Description | +|-------------|---------------------------------------------------------------------------------------------| +| count | Count of the events filtered by the snippet properties (without limit/offset) | +| output | All events collected by the snippet separated by the string in the outputSeparator property | + +### tplAgendaEventEmpty + +Only the current script properties are available as placeholders. + +### tplAgendaEventCategory + +| Placeholder | Description | +|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| alias | The alias of the category. | +| background | The background color of the category of the event. | +| foreground | The foreground color of the category of the event. | +| name | The name of the category. | +| resource_id | The id of a linked resource of the category. | +| selected | Contains `selected="selected"`, when the category request value is equal to the alias of the category. | +| url | The url that shows the event list filtered by the displayed category. Will be generated with the system/context setting `agenda.list_id`. This resource should contain an AgendaList snippet call. | + +### tplAgendaEventImage + +| Placeholder | Description | +|-------------|------------------------------------------| +| description | The description of the image. | +| idx | The number of the image starting with 1. | +| title | The title of the image. | +| url | The url that shows the event image. | + +### tplAgendaEventLocation + +| Placeholder | Description | +|-------------|--------------------------------------------------------------------------------------------------------| +| address | The address of the location. | +| alias | The alias of the location. | +| center_lat | The latitude of the center of a map of the location. | +| center_lng | The longitude of the center of a map of the location. | +| description | The description of the location. | +| lat | The latitude of the location. | +| lng | The longitude of the location. | +| name | The name of the location. | +| resource_id | The id of a linked resource of the location. | +| selected | Contains `selected="selected"`, when the location request value is equal to the alias of the location. | +| zoom | The zoom level of a map of the location. | + +### tplAgendaEventVideo + +| Placeholder | Description | +|-------------|------------------------------------------| +| description | The description of the video. | +| idx | The number of the video starting with 1. | +| title | The title of the video. | +| url | The url that shows the event video. | + +## Range placeholder format + +The `range` placeholder could be formatted with the lexicon entries +`agenda.php_format_daterange` and `agenda.php_format_separator` or the snippet +properties `daterangeFormat` and `daterangeSeparator`. The format string has to +use exactly 7 parts separated by `|`. The default english lexicon entry is +`j.| F |Y|, |g|:i a|`. + +The daterrange is formatted with the following rules: + +- If both dates are different and the hour/minute of start and end is 0, parts 4-7 are removed from start and end date. +- If both dates are different and the hour/minute of start and end is 0 and year of start and end is equal, parts 4-7 are removed from start and end date and part 3 is removed from start date. +- If both dates are different and the hour/minute of start and end is 0 and year and month of start and end are equal, parts 4-7 are removed from start and end date and parts 2-3 are removed from start date. +- If both dates are different and the hour/minute of start and end is 0 and year, month and day of start and end are equal, parts 4-7 are removed from start and end date and parts 1-3 are removed from start date. +- If both dates are different and the hour/minute of start and end is not 0 and one detail of year, month and day of start and end is not equal, all parts are used in the start and end date. +- If both dates are different and the hour/minute of start and the hour of end is 0 and all details of year, month and day of start and end are equal, parts 4-7 are removed from start date. +- If both dates are different and the hour or minute of start or the hour of end not 0 and all details of year, month and day of start and end are equal, part 7 is removed from start date. +- If both dates are equal and the hour/minute of start is 0, part 4-7 is removed from the start date and separator and end date are removed. +- If both dates are equal and the hour/minute of start is not 0, separator and end date are removed. diff --git a/en/01_Agenda/v1/04_Snippets/02_AgendaCalendar.md b/en/01_Agenda/v1/04_Snippets/02_AgendaCalendar.md new file mode 100755 index 00000000..b7072e97 --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/02_AgendaCalendar.md @@ -0,0 +1,146 @@ +This snippet displays events in a list view separared into intervals. The +snippet was introduced with Agenda 1.1.0. + +## Properties + +It uses the following snippet properties: + +| Property | Description | Default | +|--------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------| +| active | **Since 1.6.3** If this option is disabled, the active status of an event is not regarded. | 1 (Yes) | +| ajax | **Since 1.4.0** If set, the snippet output will be directly returned to the browser as a JSON result when the page is requested with the same value in the ajax request parameter. | 0 (No) | +| allowedRequestKeys | Comma-separated list of request keys, that can be used to filter the displayed events. Defaults to all allowed. | - | +| calendars | Comma-separated list of aliases of calendars to filter the displayed events. | - | +| categories | Comma separated list of aliases of categories to filter the displayed events. | - | +| categoryTpl | Name of a chunk that contains the template of one category in the category list of an event. | tplAgendaEventCategory | +| contexts | Comma separated list of context keys to filter the displayed events. | - | +| daterangeFormat | Format of the daterange displayed in an event. | - | +| daterangeSeparator | Separator in the daterange displayed in an event. | - | +| detailId | ID of a resource containing an AgendaDetail snippet call. | - | +| durationParts | Number of detail parts of the event duration output. | 1 | +| durationRound | **Since 1.5.0** Rounding type for event duration. | ceil | +| end | The end date to filter the displayed events. Must contain a [supported date and time format](https://www.php.net/manual/de/datetime.formats.php). | - | +| excludeEvents | Comma separated list of event IDs to exclude from the displayed events. | - | +| excludeRepeats | Comma separated list of repeating event IDs to exclude from the displayed events. | - | +| imageTpl | Name of a chunk that contains the template for one image in the image list of an event. | tplAgendaEventImage | +| interval | The interval into which the period between start and end date is divided. Must contain a [supported date and time format](https://www.php.net/manual/de/datetime.formats.php). | - | +| intervalTpl | Name of a chunk that contains the template for an interval. | tplAgendaEventInterval | +| listId | ID of a resource containing an AgendaList snippet call. | - | +| locale | The locale for the displayed formatted date. Defaults to the current system/context locale setting. | - | +| locations | Comma separated list of aliases of locations to filter the displayed events. | - | +| locationTpl | Name of a chunk that contains the template for the location of an event. | tplAgendaEventLocation | +| outputSeparator | An optional string to separate each tpl instance. | - | +| resourceTpl | Name of a chunk that contains the template for the linked resource of an event. | - | +| start | The start date to filter the displayed events. Must contain a [supported date and time format](https://www.php.net/manual/de/datetime.formats.php). | - | +| toPlaceholder | If set, the snippet result will be assigned to this placeholder instead of outputting it directly. | - | +| tpl | Name of a chunk that contains the template for one event. | tplAgendaEventRow | +| usergroups | Comma separated list of user group names to filter the displayed events. | - | +| users | Comma separated list of user IDs to filter the displayed events. | - | +| videoTpl | Name of a chunk that contains the template for one video in the video list of an event. | tplAgendaEventVideo | +| where | **Since 1.5.0** JSON encoded xPDO where clause to filter the displayed events. | - | +| wrapperTpl | Name of a chunk that contains the wrapper template for all events. | tplAgendaEventWrapper | + +## Placeholders + +The following placeholders are available in the different (default) chunks. Each +snippet property will be set as placeholder in each template chunk, i.e. a +snippet call ```[[!AgendaDetail? &subtitle=`whatever`]]``` will fill the +placeholder subtitle in each used chunk with the value `whatever`. + +**CAUTION:** The default template chunks for both snippets are overwritten +during each package update, so please rename the chunks before editing them. + +### tplAgendaEventRow + +| Placeholder | Description | +|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| allday | Contains 1 if the event is an all day event (otherwise 0). | +| calendar_background | The background color of the calendar of the event. | +| calendar_foreground | The foreground color of the calendar of the event. | +| calendar_name | The calendar name. | +| categories | All categories of the event formatted by the chunk set with the categoryTpl property | +| description | The title of the event. | +| detail_url | The url that shows the event detail. Will be generated with the system/context setting `agenda.detail_id`. This resource should contain an AgendaDetail snippet call. | +| duration | The formatted duration of the event. The details of the duration can be set with the `durationParts` snippet property. | +| enddate | The start date of the event formatted in ISO 8601 (can be formatted i.e. with ```[[+startdate:strtotime:date=`%a. %d.%m.%Y`]]```). | +| idx | The number of the event starting with 1. | +| images | All images of the event formatted by the chunk set with the imageTpl property | +| imageurls | An array of all image urls. The placeholder `[[+imageurls.1]]` contains the url of the first image | +| location | The location of the event formatted by the chunk set with the locationTpl property | +| range | The formatted date range of the event. The format is defined with the lexicon entries `agenda.php_format_daterange` and `agenda.php_format_separator` and can be overridden by the `daterangeFormat` snippet property. The [format rules](01_AgendaList#range-placeholder-format) are described on the AgendaList page. | +| repeating | Contains 1 if the event is an repeating event (otherwise 0). | +| resource_id | The id of a linked resource of the event. | +| startdate | The start date of the event formatted in ISO 8601 (can be formatted i.e. with ```[[+startdate:strtotime:date=`%a. %d.%m.%Y`]]```). | +| title | The title of the event. | +| videos | All videos of the event formatted by the chunk set with the videosTpl property | +| videourls | An array of all video urls. The placeholder `[[+videourls.1]]` contains the url of the first video | + +[Extended fields](../06_Extended_Fields) are available as placeholder with the prefix `extended` in the +event row template. + +### tplAgendaInterval + +| Placeholder | Description | +|-------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| count | Count of the events filtered by the snippet properties (without limit/offset) | +| output | All events in one interval collected by the snippet separated by the string in the outputSeparator property | +| startdate | The start date of the interval formatted in ISO 8601 (could be formatted i.e. with ```[[+startdate:strtotime:date=`%a. %d.%m.%Y`]]```). | +| enddate | The end date of the interval formatted in ISO 8601 (could be formatted i.e. with ```[[+startdate:strtotime:date=`%a. %d.%m.%Y`]]```). | +| range | The formatted date range of the interval. The format is defined with the lexicon entries `agenda.php_format_daterange` and `agenda.php_format_separator` and could be overridden by the `daterangeFormat` snippet property. The [format rules](01_AgendaList#range-placeholder-format) are described below. | +| idy | The number of the interval starting with 1. | + +### tplAgendaEventWrapper + +| Placeholder | Description | +|-------------|------------------------------------------------------------------------------------------------| +| output | All intervals collected by the snippet separated by the string in the outputSeparator property | + +### tplAgendaEventEmpty + +Only the current script properties are available as placeholders. + +### tplAgendaEventCategory + +| Placeholder | Description | +|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| alias | The alias of the category. | +| background | The background color of the category of the event. | +| foreground | The foreground color of the category of the event. | +| name | The name of the category. | +| resource_id | The id of a linked resource of the category. | +| selected | Contains `selected="selected"`, when the category request value is equal to the alias of the category. | +| url | The url that shows the event list filtered by the displayed category. Will be generated with the system/context setting `agenda.list_id`. This resource should contain an AgendaList snippet call. | + +### tplAgendaEventImage + +| Placeholder | Description | +|-------------|------------------------------------------| +| description | The description of the image. | +| idx | The number of the image starting with 1. | +| title | The title of the image. | +| url | The url that shows the event image. | + +### tplAgendaEventLocation + +| Placeholder | Description | +|-------------|--------------------------------------------------------------------------------------------------------| +| address | The address of the location. | +| alias | The alias of the location. | +| center_lat | The latitude of the center of a map of the location. | +| center_lng | The longitude of the center of a map of the location. | +| description | The description of the location. | +| lat | The latitude of the location. | +| lng | The longitude of the location. | +| name | The name of the location. | +| resource_id | The id of a linked resource of the location. | +| selected | Contains `selected="selected"`, when the location request value is equal to the alias of the location. | +| zoom | The zoom level of a map of the location. | + +### tplAgendaEventVideo + +| Placeholder | Description | +|-------------|------------------------------------------| +| description | The description of the video. | +| idx | The number of the video starting with 1. | +| title | The title of the video. | +| url | The url that shows the event video. | diff --git a/en/01_Agenda/v1/04_Snippets/03_AgendaDetail.md b/en/01_Agenda/v1/04_Snippets/03_AgendaDetail.md new file mode 100755 index 00000000..0e37b88d --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/03_AgendaDetail.md @@ -0,0 +1,129 @@ +This snippet displays one event in a detail view. + +## Properties + +It uses the following snippet properties: + +| Property | Description | Default | +|--------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------| +| active | If this option is disabled, the active status of an event is not regarded. | 1 (Yes) | +| ajax | **Since 1.4.0** If set, the snippet output will be directly returned to the browser as a JSON result when the page is requested with the same value in the ajax request parameter. | 0 (No) | +| allowedRequestKeys | Comma-separated list of request keys, that can be used to filter the displayed event. Defaults to all allowed. | - | +| calendars | Comma-separated list of aliases of calendars to filter the displayed event. | - | +| categories | Comma separated list of aliases of categories to filter the displayed event. | - | +| categoryTpl | Name of a chunk that contains the template of one category in the category list of an event. | tplAgendaEventCategory | +| contexts | Comma separated list of context keys to filter the displayed event. | - | +| daterangeFormat | Format of the daterange displayed in an event. | - | +| daterangeSeparator | Separator in the daterange displayed in an event. | - | +| detailId | ID of a resource containing an AgendaDetail snippet call. | - | +| durationParts | Number of detail parts of the event duration output. | 1 | +| durationRound | **Since 1.5.0** Rounding type for event duration. | ceil | +| emptyTpl | Name of a chunk that contains the template for not found event. | tplAgendaEventEmpty | +| id | ID of one event to retrieve the displayed event. | - | +| imageTpl | Name of a chunk that contains the template for one image in the image list of an event. | tplAgendaEventImage | +| listId | ID of a resource containing an AgendaList snippet call. | - | +| locale | The locale for the displayed formatted date. Defaults to the current system/context locale setting. | - | +| locations | Comma separated list of aliases of locations to filter the displayed event. | - | +| locationTpl | Name of a chunk that contains the template for the location of an event. | tplAgendaEventLocation | +| repeating | ID of one repeating event to retrieve the displayed event. | - | +| resourceTpl | Name of a chunk that contains the template for the linked resource of an event. | - | +| toPlaceholder | If set, the snippet result will be assigned to this placeholder instead of outputting it directly. | - | +| tpl | Name of a chunk that contains the template for one event. | tplAgendaEventDetail | +| usergroups | Comma separated list of user group names to filter the displayed event. | - | +| users | Comma separated list of user IDs to filter the displayed event. | - | +| videoTpl | Name of a chunk that contains the template for one video in the video list of an event. | tplAgendaEventVideo | +| where | **Since 1.5.0** JSON encoded xPDO where clause to filter the event. | - | + +## Placeholders + +The following placeholders are available in the different (default) chunks. Each +snippet property will be set as placeholder in each template chunk, i.e. a +snippet call ```[[!AgendaDetail? &subtitle=`whatever`]]``` will fill the +placeholder subtitle in each used chunk with the value `whatever`. + +**CAUTION:** The default template chunks for both snippets are overwritten +during each package update, so please rename the chunks before editing them. + +### tplAgendaEventDetail + +| Placeholder | Description | +|---------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| allday | Contains 1 if the event is an all day event (otherwise 0). | +| calendar_background | The background color of the calendar of the event. | +| calendar_foreground | The foreground color of the calendar of the event. | +| calendar_name | The calendar name. | +| categories | All categories of the event formatted by the chunk set with the categoryTpl property | +| description | The title of the event. | +| detail_url | The url that shows the event detail. Will be generated with the system/context setting `agenda.detail_id`. This resource should contain an AgendaDetail snippet call. | +| duration | The formatted duration of the event. The details of the duration can be set with the `durationParts` snippet property. | +| enddate | The start date of the event formatted in ISO 8601 (can be formatted i.e. with ```[[+startdate:strtotime:date=`%a. %d.%m.%Y`]]```). | +| images | All images of the event formatted by the chunk set with the imageTpl property | +| imageurls | An array of all image urls. The placeholder `[[+imageurls.1]]` contains the url of the first image | +| location | The location of the event formatted by the chunk set with the locationTpl property | +| range | The formatted date range of the event. The format is defined with the lexicon entries `agenda.php_format_daterange` and `agenda.php_format_separator` and can be overridden by the `daterangeFormat` snippet property. The [format rules](01_AgendaList#range-placeholder-format) are described on the AgendaList page. | +| repeating | Contains 1 if the event is an repeating event (otherwise 0). | +| resource_id | The id of a linked resource of the event. | +| startdate | The start date of the event formatted in ISO 8601 (can be formatted i.e. with ```[[+startdate:strtotime:date=`%a. %d.%m.%Y`]]```). | +| title | The title of the event. | +| videos | All videos of the event formatted by the chunk set with the videosTpl property | +| videourls | An array of all video urls. The placeholder `[[+videourls.1]]` contains the url of the first video | + +[Extended fields](../06_Extended_Fields) are available as placeholder with the prefix `extended` in the +event row template. + +### tplAgendaEventWrapper + +| Placeholder | Description | +|-------------|---------------------------------------------------------------------------------------------| +| count | Count of the events filtered by the snippet properties (without limit/offset) | +| output | All events collected by the snippet separated by the string in the outputSeparator property | + +### tplAgendaEventEmpty + +Only the current script properties are available as placeholders. + +### tplAgendaEventCategory + +| Placeholder | Description | +|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| alias | The alias of the category. | +| background | The background color of the category of the event. | +| foreground | The foreground color of the category of the event. | +| name | The name of the category. | +| resource_id | The id of a linked resource of the category. | +| selected | Contains `selected="selected"`, when the category request value is equal to the alias of the category. | +| url | The url that shows the event list filtered by the displayed category. Will be generated with the system/context setting `agenda.list_id`. This resource should contain an AgendaList snippet call. | + +### tplAgendaEventImage + +| Placeholder | Description | +|-------------|------------------------------------------| +| description | The description of the image. | +| idx | The number of the image starting with 1. | +| title | The title of the image. | +| url | The url that shows the event image. | + +### tplAgendaEventLocation + +| Placeholder | Description | +|-------------|--------------------------------------------------------------------------------------------------------| +| address | The address of the location. | +| alias | The alias of the location. | +| center_lat | The latitude of the center of a map of the location. | +| center_lng | The longitude of the center of a map of the location. | +| description | The description of the location. | +| lat | The latitude of the location. | +| lng | The longitude of the location. | +| name | The name of the location. | +| resource_id | The id of a linked resource of the location. | +| selected | Contains `selected="selected"`, when the location request value is equal to the alias of the location. | +| zoom | The zoom level of a map of the location. | + +### tplAgendaEventVideo + +| Placeholder | Description | +|-------------|------------------------------------------| +| description | The description of the video. | +| idx | The number of the video starting with 1. | +| title | The title of the video. | +| url | The url that shows the event video. | diff --git a/en/01_Agenda/v1/04_Snippets/04_AgendaDetailIcal.md b/en/01_Agenda/v1/04_Snippets/04_AgendaDetailIcal.md new file mode 100755 index 00000000..559762ba --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/04_AgendaDetailIcal.md @@ -0,0 +1,39 @@ +This snippet displays an iCalendar link or download an iCalendar file of an event. + +## Properties + +It uses the following snippet properties: + +| Property | Description | Default | +|----------------|-----------------------------------------------------------------------------------------------------|------------------------------| +| active | If this option is disabled, the active status of an event is not regarded. | 1 (Yes) | +| calendars | Comma-separated list of aliases of calendars to filter the iCal download. | - | +| categories | Comma separated list of aliases of categories to filter the iCal download. | - | +| contexts | Comma separated list of context keys to filter the iCal download. | - | +| descriptionTpl | Name of a chunk that contains the template for the description in the iCal event. | - | +| id | ID of one event to retrieve the ical event. | - | +| locale | The locale for the displayed formatted date. Defaults to the current system/context locale setting. | - | +| locations | Comma separated list of aliases of locations to filter the iCal download. | - | +| locationTpl | Name of a chunk that contains the template for the location of the ical event. | tplAgendaEventLocationICal | +| repeating | ID of one repeating event to retrieve the ical event. | - | +| tpl | Name of a chunk that contains the template for iCal download link. | tplAgendaEventDetailICalLink | +| usergroups | Comma separated list of user group names to filter the iCal download. | - | +| users | Comma separated list of user IDs to filter the iCal download. | - | +| where | **Since 1.5.0** JSON encoded xPDO where clause to filter the ical event. | - | + +## Placeholders + +The following placeholders are available in the different (default) chunks. Each +snippet property will be set as placeholder in each template chunk, i.e. a +snippet call ```[[!AgendaDetail? &subtitle=`whatever`]]``` will fill the +placeholder subtitle in each used chunk with the value `whatever`. + +**CAUTION:** The default template chunks for both snippets are overwritten +during each package update, so please rename the chunks before editing them. + +### tplAgendaEventDetailIcal + +| Placeholder | Description | +|-------------|-----------------------------------------------| +| key | The request key for the iCal download link. | +| value | The request value for the iCal download link. | diff --git a/en/01_Agenda/v1/04_Snippets/05_AgendaCalendars.md b/en/01_Agenda/v1/04_Snippets/05_AgendaCalendars.md new file mode 100755 index 00000000..994ebd26 --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/05_AgendaCalendars.md @@ -0,0 +1,57 @@ +This snippet displays a list of calendars. + +## Properties + +It uses the following snippet properties: + +| Property | Description | Default | +|--------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------| +| ajax | **Since 1.4.0** If set, the snippet output will be directly returned to the browser as a JSON result when the page is requested with the same value in the ajax request parameter. | 0 (No) | +| allowedRequestKeys | Comma-separated list of request keys, that can be used to filter the displayed calendars. Defaults to all allowed. | - | +| calendars | Comma-separated list of aliases of calendars to filter the displayed calendars. | - | +| emptyTpl | Name of a chunk that contains the template for not found calendars. | tplAgendaCalendarsEmpty | +| filterByEvents | **Since 1.5.0** If set, the calendars with no future events are filtered from the result. | 0 (No) | +| limit | Limit the number of calendars in the result. Use "0" for unlimited calendars. | 20 | +| listId | ID of a resource containing an AgendaList snippet call. | - | +| offset | The offset of calendars to skip. | - | +| outputSeparator | An optional string to separate each tpl instance. | - | +| selected | Comma separated list of calendar aliases, that have the placeholder selected filled. | - | +| sortby | **Since 1.5.0** Sort field for sorting the output. It could also contain a JSON object to sort the ouput by multiple fields like
{"AgendaCalendars.name":"ASC","AgendaCalendars.background":"DESC"}
. | sortindex | +| sortdir | **Since 1.5.0** Sort direction for sorting the output. Unused when the sortby property contains a valid JSON object. | ASC | +| toPlaceholder | If set, the snippet result will be assigned to this placeholder instead of outputting it directly. | - | +| totalVar | The key of a placeholder that indicates the total number of calendars. | agendacalendars.total | +| tpl | Name of a chunk that contains the template for one calendar. | tplAgendaCalendar | +| where | **Since 1.5.0** JSON encoded xPDO where clause to filter the calendars. | - | +| wrapperTpl | Name of a chunk that contains the wrapper template for all calendars. | tplAgendaCalendarsWrapper | + +## Placeholders + +The following placeholders are available in the different (default) chunks. Each +snippet property will be set as placeholder in each template chunk, i.e. a +snippet call ```[[!AgendaDetail? &subtitle=`whatever`]]``` will fill the +placeholder subtitle in each used chunk with the value `whatever`. + +**CAUTION:** The default template chunks for both snippets are overwritten +during each package update, so please rename the chunks before editing them. + +### tplAgendaCalendar + +| Placeholder | Description | +|-------------|--------------------------------------------------------------------------------------------------------| +| alias | The alias of the calendar. | +| background | The background color of the calendar of the event. | +| foreground | The foreground color of the calendar of the event. | +| name | The name of the calendar. | +| resource_id | The id of a linked resource of the calendar. | +| selected | Contains `selected="selected"`, when the calendar request value is equal to the alias of the calendar. | + +### tplAgendaCalendarsEmpty + +Only the current script properties are available as placeholders. + +### tplAgendaCalendarsWrapper + +| Placeholder | Description | +|-------------|------------------------------------------------------------------------------------------------| +| count | Count of the calendars filtered by the snippet properties (without limit/offset) | +| output | All calendars collected by the snippet separated by the string in the outputSeparator property | diff --git a/en/01_Agenda/v1/04_Snippets/06_AgendaCategories.md b/en/01_Agenda/v1/04_Snippets/06_AgendaCategories.md new file mode 100755 index 00000000..3fd35af8 --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/06_AgendaCategories.md @@ -0,0 +1,58 @@ +This snippet displays a list of categories. + +## Properties + +It uses the following snippet properties: + +| Property | Description | Default | +|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------| +| ajax | **Since 1.4.0** If set, the snippet output will be directly returned to the browser as a JSON result when the page is requested with the same value in the ajax request parameter. | 0 (No) | +| allowedRequestKeys | Comma-separated list of request keys, that can be used to filter the displayed categories. Defaults to all allowed. | - | +| categories | Comma-separated list of aliases of categories to filter the displayed categories. | - | +| emptyTpl | Name of a chunk that contains the template for not found categories. | tplAgendaCategoriesEmpty | +| filterByEvents | **Since 1.5.0** If set, the categories with no future events are filtered from the result. | 0 (No) | +| limit | Limit the number of categories in the result. Use "0" for unlimited categories. | 20 | +| listId | ID of a resource containing an AgendaList snippet call. | - | +| offset | The offset of categories to skip. | - | +| outputSeparator | An optional string to separate each tpl instance. | - | +| selected | Comma separated list of category aliases, that have the placeholder selected filled. | - | +| sortby | **Since 1.5.0** Sort field for sorting the output. It could also contain a JSON object to sort the ouput by multiple fields like
{"AgendaCategories.name":"ASC","AgendaCategories.background":"DESC"}
. | sortindex | +| sortdir | **Since 1.5.0** Sort direction for sorting the output. Unused when the sortby property contains a valid JSON object. | ASC | +| toPlaceholder | If set, the snippet result will be assigned to this placeholder instead of outputting it directly. | - | +| totalVar | The key of a placeholder that indicates the total number of categories. | agendacategories.total | +| tpl | Name of a chunk that contains the template for one category. | tplAgendaCategory | +| where | **Since 1.5.0** **Since 1.5.0** JSON encoded xPDO where clause to filter the categories. | - | +| wrapperTpl | Name of a chunk that contains the wrapper template for all categories. | tplAgendaCategoriesWrapper | + +## Placeholders + +The following placeholders are available in the different (default) chunks. Each +snippet property will be set as placeholder in each template chunk, i.e. a +snippet call ```[[!AgendaDetail? &subtitle=`whatever`]]``` will fill the +placeholder subtitle in each used chunk with the value `whatever`. + +**CAUTION:** The default template chunks for both snippets are overwritten +during each package update, so please rename the chunks before editing them. + +### tplAgendaCategory + +| Placeholder | Description | +|-------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| alias | The alias of the category. | +| background | The background color of the category of the event. | +| foreground | The foreground color of the category of the event. | +| name | The name of the category. | +| resource_id | The id of a linked resource of the category. | +| selected | Contains `selected="selected"`, when the category request value is equal to the alias of the category. | +| url | The url that shows the event list filtered by the displayed category. Will be generated with the system/context setting `agenda.list_id`. This resource should contain an AgendaList snippet call. | + +### tplAgendaCategoriesEmpty + +Only the current script properties are available as placeholders. + +### tplAgendaCategoriesWrapper + +| Placeholder | Description | +|-------------|-------------------------------------------------------------------------------------------------| +| count | Count of the categories filtered by the snippet properties (without limit/offset) | +| output | All categories collected by the snippet separated by the string in the outputSeparator property | diff --git a/en/01_Agenda/v1/04_Snippets/07_AgendaLocations.md b/en/01_Agenda/v1/04_Snippets/07_AgendaLocations.md new file mode 100755 index 00000000..7fe0cf60 --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/07_AgendaLocations.md @@ -0,0 +1,62 @@ +This snippet displays a list of locations. + +## Properties + +It uses the following snippet properties: + +| Property | Description | Default | +|--------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------| +| ajax | **Since 1.4.0** If set, the snippet output will be directly returned to the browser as a JSON result when the page is requested with the same value in the ajax request parameter. | 0 (No) | +| allowedRequestKeys | Comma-separated list of request keys, that can be used to filter the displayed locations. Defaults to all allowed. | - | +| emptyTpl | Name of a chunk that contains the template for not found locations. | tplAgendaLocationsEmpty | +| filterByEvents | **Since 1.5.0** If set, the locations with no future events are filtered from the result. | 0 (No) | +| limit | Limit the number of locations in the result. Use "0" for unlimited locations. | 20 | +| listId | ID of a resource containing an AgendaList snippet call. | - | +| locations | Comma-separated list of aliases of locations to filter the displayed locations. | - | +| offset | The offset of locations to skip. | - | +| outputSeparator | An optional string to separate each tpl instance. | - | +| selected | Comma separated list of calendar aliases, that have the placeholder selected filled. | - | +| sortby | **Since 1.5.0** Sort field for sorting the output. It could also contain a JSON object to sort the ouput by multiple fields like
{"AgendaLocations.name":"ASC","AgendaLocations.address":"DESC"}
. | sortindex | +| sortdir | **Since 1.5.0** Sort direction for sorting the output. Unused when the sortby property contains a valid JSON object. | ASC | +| toPlaceholder | If set, the snippet result will be assigned to this placeholder instead of outputting it directly. | - | +| totalVar | The key of a placeholder that indicates the total number of locations. | agendalocations.total | +| tpl | Name of a chunk that contains the template for one location. | tplAgendaLocation | +| where | **Since 1.5.0** JSON encoded xPDO where clause to filter the locations. | - | +| wrapperTpl | Name of a chunk that contains the wrapper template for all locations. | tplAgendaLocationsWrapper | + +## Placeholders + +The following placeholders are available in the different (default) chunks. Each +snippet property will be set as placeholder in each template chunk, i.e. a +snippet call ```[[!AgendaDetail? &subtitle=`whatever`]]``` will fill the +placeholder subtitle in each used chunk with the value `whatever`. + +**CAUTION:** The default template chunks for both snippets are overwritten +during each package update, so please rename the chunks before editing them. + +### tplAgendaLocation + +| Placeholder | Description | +|-------------|--------------------------------------------------------------------------------------------------------| +| address | The address of the location. | +| alias | The alias of the location. | +| center_lat | The latitude of the center of a map of the location. | +| center_lng | The longitude of the center of a map of the location. | +| description | The description of the location. | +| lat | The latitude of the location. | +| lng | The longitude of the location. | +| name | The name of the location. | +| resource_id | The id of a linked resource of the location. | +| selected | Contains `selected="selected"`, when the location request value is equal to the alias of the location. | +| zoom | The zoom level of a map of the location. | + +### tplAgendaLocationsEmpty + +Only the current script properties are available as placeholders. + +### tplAgendaLocationsWrapper + +| Placeholder | Description | +|-------------|------------------------------------------------------------------------------------------------| +| count | Count of the locations filtered by the snippet properties (without limit/offset) | +| output | All locations collected by the snippet separated by the string in the outputSeparator property | diff --git a/en/01_Agenda/v1/04_Snippets/08_AgendaGetDate.md b/en/01_Agenda/v1/04_Snippets/08_AgendaGetDate.md new file mode 100755 index 00000000..046c6652 --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/08_AgendaGetDate.md @@ -0,0 +1,11 @@ +This retrieves and format a date from a GET parameter. The snippet was +introduced with Agenda 1.4.0. + +## Properties + +It uses the following snippet properties: + +| Property | Description | Default | +|------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------| +| format | The output format for the date that is retrieved with a GET parameter. Must contain a [supported date and time format](https://www.php.net/manual/de/datetime.formats.php). | Y-m-d H:i:s | +| requestKey | The GET parameter key that is used to retrieve a date. | date | diff --git a/en/01_Agenda/v1/04_Snippets/09_AgendaEventGet.md b/en/01_Agenda/v1/04_Snippets/09_AgendaEventGet.md new file mode 100755 index 00000000..31c44369 --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/09_AgendaEventGet.md @@ -0,0 +1,53 @@ +This hook loads the data of an Agenda event into FormIt fields. The hook was introduced with Agenda 1.1.0. + +The event is retrieved with the event ID or the repeat ID, if the event ID is +not set. If no event can be retrieved, the hook returns false + +## FormIt Hook Properties + +The hook uses the following hook properties: + +| Property | Description | Default | +|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------| +| agendaActiveOnly | Load only active events into FormIt. | true | +| agendaCalendars | Comma-separated list of aliases of calendars to filter the loaded event. | - | +| agendaCategories | Comma separated list of aliases of categories to filter the loaded event. | - | +| agendaContexts | Comma separated list of context keys to filter the loaded event. | - | +| agendaDateformat | Format of the startdate and enddate field, set by the hook. Must contain a [supported date and time format](https://www.php.net/manual/de/datetime.formats.php). | Y-m-d H:i:s | +| agendaDateformatAllday | Format of the startdate and enddate field, set by the hook, when the event is an all day event. Must contain a [supported date and time format](https://www.php.net/manual/de/datetime.formats.php). | Y-m-d | +| agendaId | ID of one event to load into FormIt. | 0 | +| agendaLocations | Comma separated list of aliases of locations to filter the loaded event. | - | +| agendaOwnEvent | Load only own events (created by the current user) into FormIt. | false | +| agendaRepeating | ID of one repeating event to load into FormIt. | 0 | +| agendaUsergroups | Comma separated list of user group names to filter the loaded event. | - | +| agendaUsers | Comma separated list of user IDs to filter the loaded event. | - | + +## Hook fields + +The following FormIt fields are set by the loaded Agenda event in the hook. + +| Field | Description | +|-----------------|----------------------------------------------------------------------------------------------------------------| +| active | The active status of the loaded event. | +| allday | The all day status of the loaded event. | +| calendar | The alias of the calendar of the loaded event. | +| calendar_id | The id of the calendar of the loaded event. | +| category | The aliases of the categories of the loaded event. | +| content | The content of the loaded event. | +| context_key | The context key of the loaded event. | +| description | The description of the loaded event. | +| enddate | The enddate of the loaded event (or the loaded repeating event). | +| id | The id of the loaded event. | +| location | The alias of the location of the loaded event. | +| location_id | The id of the location of the loaded event. | +| repeat_enddate | The enddate of the repeats of the loaded event. | +| repeat_interval | The repeat interval of the loaded event. | +| repeat_on | The repeat weekdays of the loaded event, when the repeat type is weekly | +| repeat_ordinal | The repeat ordinal of the loaded event, when the repeat type is monthly by weekday | +| repeat_type | The repeat type of the loaded event. (1 = daily , 2 = weekly, 3 = monthly, 4 = yearly, 5 = montly by weekday ) | +| repeat_weekday | The repeat weekday of the loaded event, when the repeat type is weekly | +| repeating | The repeating status of the loaded event. | +| repeating_id | The id of the loaded repeating event. | +| resource_id | The id of the linked resource of the loaded event. | +| startdate | The startdate of the loaded event (or the loaded repeating event). | +| title | The title of the loaded event. | diff --git a/en/01_Agenda/v1/04_Snippets/10_AgendaEventSet.md b/en/01_Agenda/v1/04_Snippets/10_AgendaEventSet.md new file mode 100755 index 00000000..e122d460 --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/10_AgendaEventSet.md @@ -0,0 +1,56 @@ +This hook saves FormIt fields as an Agenda event. The hook was introduced with Agenda 1.1.0. + +It can update an existing event, if an event ID or a repeating ID is set. This +can be done by FormIt hook properties or by request parameters. The FormIt +hook properties supercede the request parameters. + +If no event_id or repeating_id is set, a new event is created. + +## FormIt Hook Properties + +The hook uses the following hook properties: + +| Property | Description | Default | +|------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------| +| agendaAllowedFields | Comma separated list of fields, that are set by the hook. Per default all fields are allowed. | - | +| agendaCalendars | Comma-separated list of aliases of calendars to filter the loaded event. | - | +| agendaCategories | Comma separated list of aliases of categories to filter the loaded event. | - | +| agendaContexts | Comma separated list of context keys to filter the loaded event. | - | +| agendaDateformat | Format of the startdate and enddate field, set by the hook. Must contain a [supported date and time format](https://www.php.net/manual/de/datetime.formats.php). | Y-m-d H:i:s | +| agendaDateformatAllday | Format of the startdate and enddate field, set by the hook, when the event is an all day event. Must contain a [supported date and time format](https://www.php.net/manual/de/datetime.formats.php). | Y-m-d | +| agendaId | ID of one event to load into FormIt. | 0 | +| agendaLocations | Comma separated list of aliases of locations to filter the loaded event. | - | +| agendaOwnEvent | Load only own events (created by the current user) into FormIt. | false | +| agendaRepeating | ID of one repeating event to load into FormIt. | 0 | +| agendaUsergroups | Comma separated list of user group names to filter the loaded event. | - | +| agendaUsers | Comma separated list of user IDs to filter the loaded event. | - | + +## Hook fields + +The following FormIt fields are used in the hook and saved in the Agenda event, when they are allowed. + +| Field | Description | +|-----------------|---------------------------------------------------------------------------------------------------------------| +| active | The active status of the saved event. | +| allday | The all day status of the saved event. | +| calendar | The alias of the calendar of the saved event. | +| calendar_id | The id of the calendar of the saved event. | +| category | The aliases of the categories of the saved event. | +| content | The content of the saved event. | +| context_key | The context key of the saved event. | +| description | The description of the saved event. | +| enddate | The enddate of the saved event (or the saved repeating event). | +| event_id | The id of the saved event. | +| location | The alias of the location of the saved event. | +| location_id | The id of the location of the saved event. | +| repeat_enddate | The enddate of the repeats of the saved event. | +| repeat_interval | The repeat interval of the saved event. | +| repeat_on | The repeat weekdays of the saved event, when the repeat type is weekly | +| repeat_ordinal | The repeat ordinal of the saved event, when the repeat type is monthly by weekday | +| repeat_type | The repeat type of the saved event. (1 = daily , 2 = weekly, 3 = monthly, 4 = yearly, 5 = montly by weekday ) | +| repeat_weekday | The repeat weekday of the saved event, when the repeat type is weekly | +| repeating | The repeating status of the saved event. | +| repeating_id | The id of the saved repeating event. | +| resource_id | The id of the linked resource of the saved event. | +| startdate | The startdate of the saved event (or the saved repeating event). | +| title | The title of the saved event. | diff --git a/en/01_Agenda/v1/04_Snippets/11_AgendaSearch.md b/en/01_Agenda/v1/04_Snippets/11_AgendaSearch.md new file mode 100755 index 00000000..3b1e0007 --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/11_AgendaSearch.md @@ -0,0 +1,20 @@ +This hook retrieves Agenda events with as faceted search in SimpleSearch. The +hook was introduced with Agenda 1.2.1. + +It fills the facet `events` in SimpleSearch. + +## SimpleSearch Hook Properties + +The hook uses the following hook properties: + +| Property | Description | Default | +|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------| +| agendaStartdate | The start date to filter the searched events. Must contain a [supported date and time format](https://www.php.net/manual/de/datetime.formats.php). | today 0:00 | +| agendaEnddate | The end date to filter the displayed events. Must contain a [supported date and time format](https://www.php.net/manual/de/datetime.formats.php). | +99 year 0:00 | +| agendaSearchLocation | Search the location address. When disabled, only the location title is searched. | true | +| agendaCategoryTpl | Name of a chunk that contains the template of one category in the category list of an event. | tplAgendaEventCategory | +| agendaImageTpl | Name of a chunk that contains the template of one image in the image list of an event. | tplAgendaEventImage | +| agendaVideoTpl | Name of a chunk that contains the template of one video in the video list of an event. | tplAgendaEventVideo | +| agendaLocationTpl | Name of a chunk that contains the template for the location of an event. | tplAgendaEventLocation | +| agendaResourceTpl | Name of a chunk that contains the template for the linked resource of an event. | tplAgendaEventResource | +| agendaEventExtractTpl | Name of a chunk that contains the template for the search extract of an event. | tplAgendaEventSearchExtract | diff --git a/en/01_Agenda/v1/04_Snippets/12_AgendaCalcDate.md b/en/01_Agenda/v1/04_Snippets/12_AgendaCalcDate.md new file mode 100755 index 00000000..e99b8209 --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/12_AgendaCalcDate.md @@ -0,0 +1,11 @@ +This output filter calculates a date with the given input and the options. The +output filter was introduced with Agenda 1.4.0. + +## Output Filter Properties + +The output filter uses the following properties: + +| Property | Description | Default | +|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|---------| +| input | A date that can be [parsed](https://www.php.net/manual/en/datetime.formats.php) by php DateTime. | - | +| options | The modifier string that alters the DateTime object. If the option is invalid, the result is empty and the modified placeholder is reset to the original value. | - | diff --git a/en/01_Agenda/v1/04_Snippets/13_AgendaCalcFirstFullWeek.md b/en/01_Agenda/v1/04_Snippets/13_AgendaCalcFirstFullWeek.md new file mode 100755 index 00000000..a2d0a70b --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/13_AgendaCalcFirstFullWeek.md @@ -0,0 +1,12 @@ +This output filter calculates the startdate of the first full week with the +given input. This snippet can be used to set the start date of the +[AgendaCalender](02_AgendaCalendar.md) snippet. The output filter was introduced +with Agenda 1.4.0. + +## Output Filter Properties + +The output filter uses the following properties: + +| Property | Description | Default | +|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|---------| +| input | A date that can be [parsed](https://www.php.net/manual/en/datetime.formats.php) by php DateTime. | - | diff --git a/en/01_Agenda/v1/04_Snippets/14_AgendaCalcLastFullWeek.md b/en/01_Agenda/v1/04_Snippets/14_AgendaCalcLastFullWeek.md new file mode 100755 index 00000000..21513484 --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/14_AgendaCalcLastFullWeek.md @@ -0,0 +1,12 @@ +This output filter calculates the enddate of the last full week with the given +input. This snippet can be used to set the end date of the +[AgendaCalender](02_AgendaCalendar.md) snippet. The output filter was introduced +with Agenda 1.4.0. + +## Output Filter Properties + +The output filter uses the following properties: + +| Property | Description | Default | +|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|---------| +| input | A date that can be [parsed](https://www.php.net/manual/en/datetime.formats.php) by php DateTime. | - | diff --git a/en/01_Agenda/v1/04_Snippets/index.md b/en/01_Agenda/v1/04_Snippets/index.md new file mode 100755 index 00000000..11331c74 --- /dev/null +++ b/en/01_Agenda/v1/04_Snippets/index.md @@ -0,0 +1,64 @@ +_Agenda_ contains some _snippets_ in the `Agenda` category. + +#### AgendaList + +The [AgendaList](01_AgendaList.md) snippet displays Agenda events in a view. + +#### AgendaCalendar + +The [AgendaCalendar](02_AgendaCalendar.md) snippet displays Agenda events in a list divided into. + +#### AgendaDetail + +The [AgendaDetail](03_AgendaDetail.md) snippet displays one Agenda event in a view. + +#### AgendaDetailIcal + +The [AgendaDetailIcal](04_AgendaDetailIcal.md) snippet displays the iCal Download link of one event and downloads the iCal file. + +#### AgendaCalendars + +The [AgendaCalendars](05_AgendaCalendars.md) snippet displays a list of Agenda calendars. + +#### AgendaCategories + +The [AgendaCategories](06_AgendaCategories.md) snippet displays a list of Agenda categories. + +#### AgendaLocations + +The [AgendaLocations](07_AgendaLocations.md) snippet displays a list of Agenda locations. + +#### AgendaGetDate + +The [AgendaGetDate](08_AgendaGetDate.md) snippet retrieves and formats a date from an GET parameter. + +## FormIt Hooks + +_Agenda_ contains FormIt/SimpleSearch _hooks_ in the `Agenda` category. + +#### AgendaEventGet + +The [AgendaEventGet](09_AgendaEventGet.md) hook allows to fill FormIt values by Agenda events. + +#### AgendaEventSet + +The [AgendaEventSet](10_AgendaEventSet.md) hook allows to set Agenda events values by FormIt. + +#### AgendaSearch + +The [AgendaSearch](11_AgendaSearch.md) hook allows to search for Agenda events in SimpleSearch faceted search. + +## Output Filter + +#### AgendaCalcDate + +The [AgendaCalcDate](12_AgendaCalcDate.md) output filter calculates a date with the given input and the options. + +#### AgendaCalcFirstFullWeek + +The [AgendaCalcFirstFullWeek](13_AgendaCalcFirstFullWeek.md) output filter calculates the startdate of the first full week with the given input. + +#### AgendaCalcLastFullWeek + +The [AgendaCalcLastFullWeek](14_AgendaCalcLastFullWeek.md) output filter calculates the enddate of the last full week with the given input. + diff --git a/en/01_Agenda/v1/05_Cronjob.md b/en/01_Agenda/v1/05_Cronjob.md new file mode 100755 index 00000000..cff897cc --- /dev/null +++ b/en/01_Agenda/v1/05_Cronjob.md @@ -0,0 +1,73 @@ +_Agenda_ can be controlled by a _cronjob command_. + +## Executing the cronjob command + +The cronjob command can be executed from the command line with + +`php /path/to/your/modx/installation/assets/components/agenda/cron.php` + +or with an external webcronjob using the following url: + +`https://your.domain/assets/components/agenda/cron.php?cronjob_id=xxx` + +The value xxx has to be filled with the random string in the MODX system setting +`agenda.cronjob_id` + +## The cronjob command tasks + +The cronjob command will run three different tasks: + +- [refresh the feeds](#refresh-the-feeds-task) +- [refresh the repeating events](#refresh-the-repeating-events-task) +- [import events](#import-events-task) + +Normally the feeds and the repeating events are refreshed together when no +property is set for the cronjob command. To run a single task you can use the +property `mode=feed` or `mode=repeating` for the cronjob: + +`php /path/to/your/modx/installation/assets/components/agenda/cron.php mode=feed` + +or + +`https://your.domain/assets/components/agenda/cron.php?cronjob_id=xxx&mode=feed` + +### Refresh the feeds task + +All active feeds are refreshed. New events of a feed are created, existing +events of a feed are changed and no longer existing events of a feed are +removed. + +### Refresh the repeating events task + +Per default each repeating event is only repeated to the maximum count of the +`agenda.repeating_max_occurance` system setting. The refresh of the repeating +events creates new repeats from the **current date** until the maximum count of +the `agenda.repeating_max_occurance` system setting. So there will be no +inifinite creation of repeats but the repeats will not stay at the limit, when +the repeating event was created. Only events after the last existing repeating +event are created and old (maybe edited) repeats are not changed. + +### Import events task + +With the property `mode=import` new events can be imported into Agenda with a +cronjob. The cronjob call has to use the full filepath in the file property. + +`php /path/to/your/modx/installation/assets/components/agenda/cron.php mode=import file=/path/to/the/file` + +or + +`https://your.domain/assets/components/agenda/cron.php?cronjob_id=xxx&mode=import&file=/path/to/the/file` + +The import uses the same code as the import events button in the [events +tab](02_Custom_Manager_Page/02_Events.md) of the custom manager page. The import +mode is append. The import can be overridden in an [Agenda +module](02_Custom_Manager_Page/07_Modules.md). + +## Debug the cronjob + +To detect cronjob issues, you can enable the Agenda [system +setting](02_Custom_Manager_Page/08_Settings) `agenda.debug`. The file +`{core_path}/cache/logs/agenda.log` will then contain a lot of debug +information. Per default cronjob errors are logged in the standard MODX error +log. + diff --git a/en/01_Agenda/v1/06_Extended_Fields.md b/en/01_Agenda/v1/06_Extended_Fields.md new file mode 100755 index 00000000..b1d2cbb5 --- /dev/null +++ b/en/01_Agenda/v1/06_Extended_Fields.md @@ -0,0 +1,85 @@ +## Extended Event Fields + +The extended event fields were introduced with Agenda 1.1.0. + +Each event in Agenda can use predefined extended fields. The field values are +stored as JSON encoded array in a text field. So sorting and filtering by +extended fields is not possible. + +To define the extended fields the system setting `agenda.extended_event_fields` +has to be filled with a nested JSON encoded array. The following value gives an +example: + +``` +[ + { + "name": "price", + "label": "Price" + }, + { + "fields": [ + { + "xtype": "numberfield", + "name": "minimum", + "renderer": "agenda-combo-example-resource", + "label": "Minimum number of participants", + "width": 0.5, + "column_label": "min.", + "column_width": 50 + "hidden": false + }, + { + "xtype": "numberfield", + "name": "maximum", + "renderer": "agenda-combo-example-resource", + "label": "Maximum number of participants", + "width": 0.5, + "column_label": "max.", + "column_width": 50, + "hidden": false + } + ] + } +] +``` + +It will add the fields price, and the fields minimum and maximum in two columns +to the event create/update window. + +Each array will create one extended field. The `name` key is required. The +`label` key will be used, when it exists. Otherwise, a lexicon entry with the +field name prefixed by `agenda.extended.` is searched in the lexicon. An `xtype` +key will be used, when it exists. Otherwise, the xtype defaults to `textfield`. +A `renderer` key will be used, when it exists. The renderer has to be defined in +the file referenced in the `agenda.extended_xtypes_script` system setting. + +If a nested `fields` key contains an array value, this value will be used for +subfields in columns. The `width` key inside is then used for the subfield +column width. + +The extended fields can also generate columns in the events grid. The +`column_label` key is required to add a column in the grid. The `column_width` +key will define the width of the grid column. The column_width defaults to 100. +The column can be hidden in the grid with the `hidden` key. + +Extended fields are available as placeholder with the prefix `extended` in the +event row template. The `price` field from the example will be available with +the `[[+extended.price]]` placeholder. + +The setting can use `@FILE` or `@CHUNK` bindings. Path +placeholders like `{core_path}`, `{base_path}` and `{assets_path}` can be used. +All paths have to stay inside the MODX base path because of security reasons. + +## Extended Repeat Fields + +The extended repeat fields were introduced with Agenda 1.4.0. + +They work the same as the extended event fields, can use `@FILE` or `@CHUNK` +bindings and are shown in the edit repeat window and the repeats grid. + +## Extended Location Fields + +The extended location fields were introduced with Agenda 1.4.0. + +They work the same as the extended event fields, can use `@FILE` or `@CHUNK` +bindings and are shown in the edit location window and the locations grid. diff --git a/en/01_Agenda/v1/07_Export_Import_Events.md b/en/01_Agenda/v1/07_Export_Import_Events.md new file mode 100755 index 00000000..23f69c2e --- /dev/null +++ b/en/01_Agenda/v1/07_Export_Import_Events.md @@ -0,0 +1,21 @@ +## Export and Import Events + +The export and import of events were introduced with Agenda 1.5.0. + +To export or import the events the user has to get the `agenda_export` or +`agend_import` permissions. After that an export and import button is displayed +right of the create event button in the events tab of the custom manager page. + +The export and import format can be set with the `agenda.import_export_type` +system setting. The supported formats are `csv`, `excel` and `yaml`. The default +format is `csv`. + +The default export method will create a list of events for repeating events. If +the repeating event does not have an identifier for the main event (i.e. by a +field in agenda.extended_event_fields), it is difficult to reimport those +events. During an import, events with the same event data (except start and end +dates) are treated as a repeating event. The repeat is set to user defined and +the repeat data is set for each recurrence. + +The import/export methods can be overridden in a [Agenda +module](02_Custom_Manager_Page/07_Modules.md) with extended methods. diff --git a/en/01_Agenda/v1/08_System_Events.md b/en/01_Agenda/v1/08_System_Events.md new file mode 100755 index 00000000..ae8c2a10 --- /dev/null +++ b/en/01_Agenda/v1/08_System_Events.md @@ -0,0 +1,27 @@ +## System Events + +The OnAgendaBeforeSave, OnAgendaSave and OnAgendaBeforeRemove system events were +introduced in Agenda 1.5.0. + +The OnAgendaValidate system event was introduced in Agenda 1.6.3. + +The use of these events allows additional code to be executed before and after +saving and before deleting Agenda database entries. + +The following Agenda database objects invoke the system events: AgendaCalendars, +AgendaCategories, AgendaEventCursus, AgendaEventDates, AgendaEventImages, +AgendaEvents, AgendaEventVideos and AgendaLocations. + +The following properties can be used in the plugin events: + +| Property | Content | +|-----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| mode | The state of the Agenda object. It can contain the following states: `modSystemEvent::MODE_NEW` or `modSystemEvent::MODE_UPD`. Not available in OnAgendaBeforeRemove | +| className | The class name of the saved object. | +| id | The identifier of the saved object. | +| object | The Agenda object. | + +Skeleton classes for the events can be found in +`core/components/agenda/src/Plugins/Events`. To use them, you have to remove the +underscore prefix from the filename and activate the according event in the +Agenda plugin. diff --git a/en/01_Agenda/v1/09_Tutorials/Dynamic_Opening_Hours.md b/en/01_Agenda/v1/09_Tutorials/Dynamic_Opening_Hours.md new file mode 100644 index 00000000..4f83c692 --- /dev/null +++ b/en/01_Agenda/v1/09_Tutorials/Dynamic_Opening_Hours.md @@ -0,0 +1,90 @@ +Using Agenda, you can manage and display dynamic opening hours on your site. +When you've completed this tutorial, you'll have a simple list showing the +opening hours in the next week. + +![](img/opening-hours.jpg) + +[TOC] + +## Basic Setup + +First create a new Calendar under Extras > Agenda > Calendars tab. Name it +"Opening Hours" with an alias of "openinghours", or something similar. Make sure +it's active, and give it a recognisable color. + +In your events overview, start adding (repeating) events to your new calendar. + +If you're **closed** on a certain day, add an **all day event** with what you +want to show as the event title (e.g. "Closed", or "Closed for private party"). + +If you're **open** on a certain day, add an event with a start and end date, +which corresponds with your opening hours. + +Use the repeating events' functionality to automatically repeat the opening hours +weekly. Once created, you can edit the start and end date/time of an event from +the Repeats tab, for when the opening hours are different. + +**It's important to have an event for each day of the week**. If you're missing +*a day, it won't show up in our list of opening hours at all. + +If you add multiple events for a single day (e.g. if the store is open in the +morning and afternoon, but closed during lunch), each one will show separately +in the list. + +## Snippets & Chunks + +To render the opening hours, we'll use the +[AgendaList](../04_Snippets/01_AgendaList.md) snippet with some custom chunks and +logic. + +Here's our `AgendaList` call; make sure to adjust the `&calendars` filter to +match the alias of your opening hours calendar. + +```html + + + [[!AgendaList? + &calendars=`openinghours` + &tpl=`AgendaOpeningHours` + &sortby=`{ + "startdate":"ASC" + }` + &end=`[[!*id:notempty=`+6 days`:strtotime:date=`%Y-%m-%d`]] 23:59` + ]] + +
+``` + +We're using a little trick to automatically set the `&end` property 7 days in +advance (which uses `+6 days` as today is the first day), and let Agenda +automatically start on todays' events, sorting by the start date. + +Create the **AgendaOpeningHours** chunk with the following: + +```html +[[+startdate:strtotime:date=`%Y-%m-%d`:toPlaceholder=`start_ymd`]] +[[+id:notempty=`now`:strtotime:date=`%Y-%m-%d`:toPlaceholder=`today_ymd`]] + + + [[+startdate:strtotime:date=`%A`:ucfirst]] + + + [[+startdate:strtotime:date=`%d %b`]] + + + [[+allday:neq=`1`:then=` + [[+startdate:strtotime:date=`%H.%M`]]–[[+enddate:strtotime:date=`%H.%M`]]hr + `:else=` + [[+title]] + `]] + + +``` + +Some notes: + +- First we're creating a placeholder `start_ymd` and `today_ymd` dynamically bases on the startdate for the event and the current time respectively. We use those in the wrapping `` tag to highlight events for today in bold. +- We parse the startdate into the name of the day in the first cell. If this is in the wrong language, make sure to update the `locale` system setting in MODX to the right value. +- In the second cell we're outputting the date (e.g. `8 Oct`). You can skip this if you want, but it can be useful to show what exact date the opening hours are for to indicate that they may differ from week to week. +- In the third cell we have the logic that switches between open and closed. If the event is not an all-day event, we output the hours of the event as open hours. For an all-day event, we output the title of the event (e.g. "Closed" or "Closed for private party"). + diff --git a/en/01_Agenda/v1/09_Tutorials/Frontend_Editing.md b/en/01_Agenda/v1/09_Tutorials/Frontend_Editing.md new file mode 100644 index 00000000..8175920f --- /dev/null +++ b/en/01_Agenda/v1/09_Tutorials/Frontend_Editing.md @@ -0,0 +1,110 @@ +Using the Agenda FormIt hooks, you can create and edit events by users in the +frontend. When you've completed this tutorial, you'll can create and edit an +event on a frontend page. + +[TOC] + +## Basic Setup + +First install FormIt and create a new MODX Resource. Then create a new Calendar +under Extras > Agenda > Calendars tab. Name it i.e. "User Events" with an alias +of "userevents" and make sure it's active. + +## FormIt Call and form code + +To render and execute the form, we have to add a FormIt call to a MODX resource. +This FormIt Call uses the [AgendaEventGet](../04_Snippets/09_AgendaEventGet.md) and +the [AgendaEventSet](../04_Snippets/10_AgendaEventSet.md) hooks. + +Here's our `FormIt` example call; make sure to adjust the `&agendaEvent` property to +the ID of an existing event, that should be editable in the frontend. + +```html +[[!FormIt? + &successMessage=`The event was edited!` + &hooks=`agendaeventset` + &preHooks=`agendaeventget` + &agendaEvent=`xxx` + &clearFieldsOnSuccess=`0` +]] +``` + +The form code (based on Bootstrap 3) should be added below of the `FormIt` call with the following content: + +``` +[[!+fi.validation_error_message:notempty=``]] +[[!+fi.successMessage:notempty=``]] + +
+
+
+ + +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+
+``` + +On the page with the FormIt call the title, the start date, the end date, the +category and the description of an existing event can be edited. The category +can be set with a dropdown showing all active categories. + +Some notes: + +- The `agendaEvent` property can be set by request parameter. Please make sure +that all events on your page can be edited, if you allow this. You can +restrict the editing to events created by the current user with the +`agendaOwnEvent` property. +- You can't set multiple categories with the dropdown at the moment, because of +a restriction in the `AgendaCategories` snippet. +- If you change the `agendaEvent` property to `agendaRepeating`, you can edit +the start date and end date of the repeating event. The other fields will change +the event itself. +- All editable fields are shown on the documentation of the +[AgendaEventGet](../04_Snippets/09_AgendaEventGet.md) and the +[AgendaEventSet](../04_Snippets/10_AgendaEventSet.md) hooks. diff --git a/en/01_Agenda/v1/09_Tutorials/FullCalendar_Display.md b/en/01_Agenda/v1/09_Tutorials/FullCalendar_Display.md new file mode 100644 index 00000000..c45b08cc --- /dev/null +++ b/en/01_Agenda/v1/09_Tutorials/FullCalendar_Display.md @@ -0,0 +1,65 @@ +You can use the FullCalendar 3 script in the frontend with the following steps. + +[TOC] + +## Basic Setup + +First rename the file assets/components/agenda/_overview.php to overview.php. +Afterwards edit it and remove the exit(); in line 12. + +The Agenda backend uses FullCalendar for the calendar display. You have to +create a working FullCalendar script according to the [FullCalendar 3 +documentation](https://fullcalendar.io/docs/v3/installation) or the +[current FullCalendar documentation](https://fullcalendar.io/docs/getting-started). + +## Restrict the request + +If you need to restict the overview connector to a special calendar, category, +time range etc., you can apply your own request variables after the line 29 in +the overview connector. + +## Call the frontend scripts + +Finally, you have to initialize the FullCalendar script with the following code: + +### FullCalendar 3 + +```js +$('#fullcalendar').fullCalendar({ + events: { + url: 'assets/components/agenda/overview.php', + type: 'POST', + startParam: 'startdate', + endParam: 'enddate', + data: function () { + return { + // calendars: calendars || 0, + // categories: categories || 0, + // query: query || '', + limit: 0 + }; + } + } +}); +``` + +### FullCalendar 4 and later + +```js +$('#fullcalendar').fullCalendar({ + events: { + url: 'assets/components/agenda/overview.php', + type: 'POST', + startParam: 'startdate', + endParam: 'enddate', + extraParams: function () { + return { + // calendars: calendars || 0, + // categories: categories || 0, + // query: query || '', + limit: 0 + }; + } + } +}); +``` diff --git a/en/01_Agenda/v1/09_Tutorials/img/opening-hours.jpg b/en/01_Agenda/v1/09_Tutorials/img/opening-hours.jpg new file mode 100644 index 00000000..bbb06dc4 Binary files /dev/null and b/en/01_Agenda/v1/09_Tutorials/img/opening-hours.jpg differ diff --git a/en/01_Agenda/v1/10_FAQ.md b/en/01_Agenda/v1/10_FAQ.md new file mode 100755 index 00000000..9cb2c00f --- /dev/null +++ b/en/01_Agenda/v1/10_FAQ.md @@ -0,0 +1,96 @@ +We're collecting the questions we get most often into a FAQ. If your question is +not in the list, please reach out to us via treehillstudio-support@modmore.com, +and we would be glad to help. + +[TOC] + +## How are events displayed on the website? + +To render events to your visitors, you can use the provided snippets: + +- [AgendaList](04_Snippets/01_AgendaList) used for rendering a list of events +- [AgendaCalendar](04_Snippets/02_AgendaCalendar) used for rendering events in a list divided into intervals (i.e. days) +- [AgendaDetail](04_Snippets/03_AgendaDetail) used for showing one specific event on a detail page + +There are other snippets to help you render calendars, categories, and locations. + +## How can an event repeat more than 100 times? + +By default, repeating events are scheduled for 100 recurrences. + +You have two possibilitiesto change that: + +- [Set up a cron job](05_Cronjob) to refresh repeating events for up to 100 repeats in the future from the current date. +- Increase the `agenda.repeating_max_occurance` [system setting](02_Custom_Manager_Page/08_Settings) to a larger value. + +## Can events, categories, calendars or locations be connected to a resource? + +Yes! + +Agenda comes with a number of [system +settings](02_Custom_Manager_Page/08_Settings). Configure them with a comma +separated list of resource IDs to use as parent resources. When set up, a new +resource selection field will be added to the edit windows in the manager. + +- For events: `agenda.parents_event` +- For categories: `agenda.parents_category` +- For calendars: `agenda.parents_calendar` +- For locations: `agenda.parents_location` + +## How often is an event feed refreshed? + +When creating the [feed](02_Custom_Manager_Page/06_Feeds) for events to be +imported, you can set how often the feed should be checked for new or updated +events, with a minimum interval of once a minute. + +You also need to set up the cron job to fire often enough for the feed refreshes +to happen at the right time. + +## Can a map be used in the location address tab? + +Yes, you will need to enter a [Google Maps API +Key](https://developers.google.com/maps/documentation/javascript/get-api-key) in +the `agenda.google_maps_api_key` system setting to use the map. + +In the project in the Google Cloud Platform console, activate the Maps +JavaScript API and the Geocoding API. + +# What's the difference between a calendar and a category? + +They're both ways of organising your events into logical sections, and can be +filtered on in the [AgendaList](04_Snippets/01_AgendaList) snippet. + +A Calendar is best seen as the "owner" or "target" for an event. For example a +conference center can use calendars for organising events as "Public events", +"Private parties" and "Staff-only events", which are then shown in different +sections of the website. An event must have one Calendar. + +A Category is then the type of event, which can be a sub-filter on the detail +pages. For example "Weddings", "Conference", "Expo", "Training/workshops". An +event can have many categories. + +For events grouped into a location or room, you can use the Locations +functionality as well. That can also be used with maps, ideal for businesses +with different venues or events hosted in varying places. + +## Is the cron job required? + +If you use Feeds or repeating events, yes, the cron job is required for Agenda +to work as expected. + +If your server doesn't allow you to configure cron jobs, you can trigger it +through web requests as well using online cron job services. + +## Can the cron job log more information? + +Yes, enable the `agenda.debug` [system +setting](02_Custom_Manager_Page/08_Settings). A new log will be created in +`{core_path}/cache/logs/agenda.log` with a lot of debug information. + +By default, errors are logged to the standard MODX error log. + +## I can't use my own daterange format in the lexicon or in the snippet properties + +|The format string has to use exactly 7 parts separated by `|`. The description| +of the formatting rules can be found below the placeholder descriptions on the +[AgendaList](04_Snippets/01_AgendaList#range-placeholder-format) snippet description. diff --git a/en/01_Agenda/v1/index.md b/en/01_Agenda/v1/index.md new file mode 100644 index 00000000..79e1ed85 --- /dev/null +++ b/en/01_Agenda/v1/index.md @@ -0,0 +1,16 @@ +--- +title: Agenda +description: Documentation for Agenda, a premium calendar for MODX by Treehill Studio. +--- + +[Agenda](https://modmore.com/agenda/) is a feature rich MODX calendar extra. It comes with a lot of options like the ability to create and edit repeating events, assign categories and a MODX resource to an event. The location of an event can be displayed with Google Maps. It also supports importing an external iCalendar/XML feed into one calendar, which can be updated with a cronjob. Events can be assigned to a MODX user, usergroup or context. + +It is a perfect solution for users looking for an extensive MODX event management calendar or just a well-supported MODX calendar component. + +# Recommended Reading + +- [Installation](01_Installation) +- [Custom Manager Page](02_Custom_Manager_Page) +- [Snippets](04_Snippets) +- [FAQ](10_FAQ) + diff --git a/en/01_Commerce/images/gateways/paypal-nvp.jpg b/en/01_Commerce/images/gateways/paypal-nvp.jpg new file mode 100644 index 00000000..f51844e0 Binary files /dev/null and b/en/01_Commerce/images/gateways/paypal-nvp.jpg differ diff --git a/en/01_Commerce/images/gateways/paypal-tools.jpg b/en/01_Commerce/images/gateways/paypal-tools.jpg new file mode 100644 index 00000000..5e8d62f1 Binary files /dev/null and b/en/01_Commerce/images/gateways/paypal-tools.jpg differ diff --git a/en/01_Commerce/images/gettingstarted/cron-notok.jpg b/en/01_Commerce/images/gettingstarted/cron-notok.jpg new file mode 100644 index 00000000..ddcd2fd5 Binary files /dev/null and b/en/01_Commerce/images/gettingstarted/cron-notok.jpg differ diff --git a/en/01_Commerce/images/gettingstarted/cron-ok.jpg b/en/01_Commerce/images/gettingstarted/cron-ok.jpg new file mode 100644 index 00000000..4703cf1d Binary files /dev/null and b/en/01_Commerce/images/gettingstarted/cron-ok.jpg differ diff --git a/en/01_Commerce/images/gettingstarted/multilingual-ex.jpg b/en/01_Commerce/images/gettingstarted/multilingual-ex.jpg new file mode 100644 index 00000000..75320bd8 Binary files /dev/null and b/en/01_Commerce/images/gettingstarted/multilingual-ex.jpg differ diff --git a/en/01_Commerce/images/modules/create-refund.jpg b/en/01_Commerce/images/modules/create-refund.jpg new file mode 100644 index 00000000..e4a94f66 Binary files /dev/null and b/en/01_Commerce/images/modules/create-refund.jpg differ diff --git a/en/01_Commerce/images/products/collections_view_column_edit.png b/en/01_Commerce/images/products/collections_view_column_edit.png new file mode 100644 index 00000000..cae7e26b Binary files /dev/null and b/en/01_Commerce/images/products/collections_view_column_edit.png differ diff --git a/en/01_Commerce/images/products/collections_view_config.png b/en/01_Commerce/images/products/collections_view_config.png new file mode 100644 index 00000000..479a2e50 Binary files /dev/null and b/en/01_Commerce/images/products/collections_view_config.png differ diff --git a/en/01_Commerce/images/products/collections_view_custom.png b/en/01_Commerce/images/products/collections_view_custom.png new file mode 100644 index 00000000..bf02137a Binary files /dev/null and b/en/01_Commerce/images/products/collections_view_custom.png differ diff --git a/en/01_Commerce/images/products/collections_view_grid.png b/en/01_Commerce/images/products/collections_view_grid.png new file mode 100644 index 00000000..a771cf38 Binary files /dev/null and b/en/01_Commerce/images/products/collections_view_grid.png differ diff --git a/en/01_Commerce/images/products/collections_view_json.png b/en/01_Commerce/images/products/collections_view_json.png new file mode 100644 index 00000000..a767832c Binary files /dev/null and b/en/01_Commerce/images/products/collections_view_json.png differ diff --git a/en/01_Commerce/images/products/matrix-empty.jpg b/en/01_Commerce/images/products/matrix-empty.jpg new file mode 100644 index 00000000..3fbe756b Binary files /dev/null and b/en/01_Commerce/images/products/matrix-empty.jpg differ diff --git a/en/01_Commerce/images/products/matrix-first-order-rows.jpeg b/en/01_Commerce/images/products/matrix-first-order-rows.jpeg new file mode 100644 index 00000000..51e46adc Binary files /dev/null and b/en/01_Commerce/images/products/matrix-first-order-rows.jpeg differ diff --git a/en/01_Commerce/images/products/matrix-first-order.jpg b/en/01_Commerce/images/products/matrix-first-order.jpg new file mode 100644 index 00000000..2d05ea5f Binary files /dev/null and b/en/01_Commerce/images/products/matrix-first-order.jpg differ diff --git a/en/01_Commerce/images/products/matrix-first.jpg b/en/01_Commerce/images/products/matrix-first.jpg new file mode 100644 index 00000000..3fde83b8 Binary files /dev/null and b/en/01_Commerce/images/products/matrix-first.jpg differ diff --git a/en/01_Commerce/images/products/matrix-optgroup-row.jpg b/en/01_Commerce/images/products/matrix-optgroup-row.jpg new file mode 100644 index 00000000..4ad03a4e Binary files /dev/null and b/en/01_Commerce/images/products/matrix-optgroup-row.jpg differ diff --git a/en/01_Commerce/images/products/matrix-sample.jpg b/en/01_Commerce/images/products/matrix-sample.jpg new file mode 100644 index 00000000..4515da23 Binary files /dev/null and b/en/01_Commerce/images/products/matrix-sample.jpg differ diff --git a/en/01_Commerce/images/products/matrix-table.jpg b/en/01_Commerce/images/products/matrix-table.jpg new file mode 100644 index 00000000..fe28f191 Binary files /dev/null and b/en/01_Commerce/images/products/matrix-table.jpg differ diff --git a/en/01_Commerce/v1/00_Requirements.md b/en/01_Commerce/v1/00_Requirements.md index 496ac499..eff8696b 100644 --- a/en/01_Commerce/v1/00_Requirements.md +++ b/en/01_Commerce/v1/00_Requirements.md @@ -1,7 +1,8 @@ -Commerce has the following requirements to run and/or to enable live mode. When Commerce is installed, the checklist under Configuration will help you make sure all requirements are met. +Commerce has the following requirements to run and/or to enable live mode. When Commerce is installed, the checklist under Configuration will help you make sure all requirements are met. -- MODX 2.5.2 or higher, and all its requirements -- PHP 5.5 or higher, 5.6 or 7.x encouraged. +- MODX 2.7.0 or higher, and all its requirements; 2.8 or 3.0 recommended +- PHP 7.1.5 or higher, 7.4 or 8.0 recommended + - Starting with Commerce 1.3, the lowest supported version is PHP 7.4 - Website accessible over HTTPS Payment gateways communicate over a HTTPS connection, as do some other integrations, so your server needs to be capable of opening secure connections. If you're able to download Commerce from the modmore package provider that's a good sign. @@ -14,9 +15,8 @@ Payment gateways communicate over a HTTPS connection, as do some other integrati We strongly recommend verifying the following in your MODX configuration. -- Latest MODX version (2.5.2 at the very least) -- Email sending should be set up with an authenticated SMTP email account. Using services like Amazon Simple Email Service, Mandrill, or Mailgun is strongly encouraged. -- Emails sent via MODX should have matching DKIM and SPF set up. Use [Mail Tester](https://www.mail-tester.com/) to verify your emails have a good chance of getting delivered. -- Friendly URLs should be enabled, including `friendly_alias_path`. -- The `core` folder should either be moved outside the webroot, or be renamed and locked down to prevent direct access. - +- Latest MODX version (either 2.8 or MODX3) +- Email sending should be set up with an authenticated SMTP email account. Using services like Amazon Simple Email Service, Mandrill, or Mailgun is strongly encouraged. +- Emails sent via MODX should have matching DKIM and SPF set up. Use [Mail Tester](https://www.mail-tester.com/) to verify your emails have a good chance of getting delivered. +- Friendly URLs should be enabled, including `friendly_alias_path`. +- The `core` folder should be locked down to prevent direct access. diff --git a/en/01_Commerce/v1/01_Getting_Started/02_Configuration.md b/en/01_Commerce/v1/01_Getting_Started/02_Configuration.md index a3a3b3db..288be80a 100644 --- a/en/01_Commerce/v1/01_Getting_Started/02_Configuration.md +++ b/en/01_Commerce/v1/01_Getting_Started/02_Configuration.md @@ -6,123 +6,133 @@ On this page: ## The Commerce Dashboard -Whenever we talk about the Commerce Dashboard, we mean Extras » Commerce in your MODX Manager. This section of your MODX installation contains the configuration, products, reporting and more. +Whenever we talk about the Commerce Dashboard, we refer to the **Extras » Commerce** section in your MODX Manager. This section of your MODX installation contains the orders, products, configuration, reporting and more. ## Choosing Modules to use -One of the first things you should do is decide whatmodules you want to use. In Commerce, many features are implemented as optional modules that can be enabled/disabled at will, and may contain additional configuration options. - -The majority of modules ship with the Commerce core, but [additional extensions](https://www.modmore.com/commerce/extensions/) are also available from modmore or third parties. +One of the first things you should do is decide which modules you want to use, because this will determine what features are available and need to be configured. + +In Commerce, many features are implemented as optional modules that can be enabled/disabled at will, and may contain additional configuration options. The majority of modules ship with the Commerce core, but [additional extensions](https://modmore.com/commerce/extensions/) are also available. Some extensions were built by modmore, and are covered by your standard support, while others have been built by the larger community and are _not_ covered by standard support. -In the Commerce Dashboard, navigate to Configuration » Modules to take a look at the modules that are available. +In the Commerce Dashboard, navigate to **Configuration » Modules** to take a look at the available modules. ![A collection of modules that are installed with Commerce](../../images/gettingstarted/modules.jpg) -To enable and configure a module, click its name in the list. You can enable modules in either test, live, or both modes by checking the appropriate boxes. +To enable and configure a module, click its name in the list. There you can enable modules in either test mode, live mode, or both modes by checking the appropriate boxes. -Which modules you'll use depend on the type of shop and how you want to run things. We'll highlight a couple here. +Which modules you use depends on the type of shop and how the shop will be run. We'll highlight a couple of common modules here, but it's recommended to go through the list and look at the descriptions to see if any others might be useful for your shop. -Note that the names are translated, so if you use the manager in a different language than English they will be named differently and may be in a different order. +**Note:** The module names are translated, so if you use the manager in a different language than English they will be named differently and may be in a different order. ### Customer, Address, and Shipping related -We **strongly recommended** to enable the [Basic Address Validation](../50_Modules/Address_Validation/Basic) module. This module ensures that address information is filled in before the customer can move along in the checkout. In the module configuration you can enter the fields that should be required, depending on your locality, the `state` field may be best taken out. +It is **strongly recommended** to enable the [Basic Address Validation](../50_Modules/Address_Validation/Basic) module. This module ensures that address information is filled in before the customer can move along in the checkout. In the module configuration, you can enter the fields that should be required depending on your locality. For example the `state` field is not required in a large part of the world. + +You should also enable either the [Autofill GeoIP](../50_Modules/Cart/AutoFillGeoIP) module or the [Default Address](../50_Modules/Cart/DefaultAddress) module. These modules will set an expected address on the order before the customer gets to the address step. This expected address is used by the taxes and shipping configuration to determine what rates and options to show before the customer entered their information. -You should also enable either [Autofill GeoIP](../50_Modules/Cart/AutoFillGeoIP) or the [Default Address](../50_Modules/Cart/DefaultAddress) module. These modules will set an expected address on the order before the customer gets to the address step, which is used by your taxes and shipping configuration to determine what rates and options to show in the cart. +- The [Default Address module](../50_Modules/Cart/DefaultAddress) is useful if you serve a distinct demographic. For example, if you only (or predominantly) ship to one country or state, you can configure the Default Address module to use that by default, which should be accurate for the majority of your customers. +- If your customer base is more spread out, the Autofill GeoIP module will automatically geolocate the customer by their IP address and use the country (and optionally the state) instead. This uses the [ipinfo.io](https://ipinfo.io/) service (free for up to 1000 lookups per day) which is fairly accurate. -- The Default Address module is useful if you serve a distinct demographic; for example if you only (or predominantly) ship to one country or state, you can configure the Default Address module to use that by default, which should be accurate for the majority of your customers. -- If your customer-base is more spread out, the Autofill GeoIP module will automatically geolocate the customer by their IP address and use the country (and optionally state) instead. This uses the [ipinfo.io](https://ipinfo.io/) service (free for up to 1000 lookups per day). +If you only sell in specific countries, the [Country Validation](../50_Modules/Address_Validation/Country) module is useful to restrict country selection. (Note that this does not remove countries from the country field in the address step, but you can do that by changing the templates.) -If you only sell in specific countries, the [Country Validation](../50_Modules/Address_Validation/Country) module is useful to restrict that. +If you require the customer to accept terms and conditions before initiating a payment, you can use the [Accept Terms](../Modules/Cart/AcceptTerms) module. ### Discounts -You'll likely want to enable the [Coupons](../50_Modules/Discounts/Coupons) module to get access to coupon codes. After enabling the module, refresh the page to see the Coupons tab being added to the top navigation. +You'll likely want to enable the [Coupons](../50_Modules/Discounts/Coupons) module to get access to coupon codes. After enabling the module, refresh the page to see the Discounts tab added to the top navigation. + +There is also a [User & Usergroup Discounts](../50_Modules/Discounts/UserDIscounts) module that can be used for percentage discounts for users or user groups, accessible from the same Discounts tab once the module is enabled. ### Taxes -- If you sell to customers in the European Union, enable the [EU VAT](../50_Modules/Taxes/EUVat) module to enable the EU VAT Rate Provider that enables automatically up-to-date tax rates across all countries in the EU. -- If you sell to customers in the United States, the [TaxJar](../50_Modules/Taxes/TaxJar) module can be used to get automated sales tax calculations. +Very few people enjoy paying taxes, but it is important to charge the right taxes to your customers. + +- If you sell to customers in the European Union, enable the [EU VAT](../50_Modules/Taxes/EUVat) module to enable the EU VAT Rate Provider that enables automatically up-to-date tax rates across all countries in the EU. This loads (and caches) tax rates from an open-source, community-maintained dataset for standard and reduced tax rates around the EU. -We'll look at configuring the actual [tax rates](../Taxes) in the next sections. +- If you sell to customers across the United States, the [TaxJar](../50_Modules/Taxes/TaxJar) module can be used to get automated sales tax calculations. This service covers virtually all possible Sales Tax rules, including product-specific exemptions if you configure the right product codes, and can also be used to help with your tax reporting, but does have a monthly cost to use. + +For all other regions, or if you prefer to manually set rates, you can use the standard configuration. We'll look at configuring the actual [tax groups and rates](../Taxes) in a minute. ### Products & Cart -Enable [CombineProducts](../50_Modules/Cart/CombineProducts) if you want multiple items with the same product to be combined into a single item in the cart. Note that this is not compatible with [ItemData](../50_Modules/Cart/ItemData) which we'll discuss later. +Enable [CombineProducts](../50_Modules/Cart/CombineProducts) if you want multiple items with the same product to be combined into a single item in the cart. Note that this is not compatible with [ItemData](../50_Modules/Cart/ItemData), which we'll discuss later. ## Setting up Statuses -The default installation created a simple status workflow for you. In Configuration > Statuses you can see that in action. +The default installation created a simple [status workflow](../Statuses) for you. At **Configuration > Statuses** you can see that in action. ![Default Status Workflow in Commerce](../../images/gettingstarted/statusworkflow.jpg) -For now, we'll leave that as-is, but later on you may want to change the emails that get send when an order is paid. Click on "Payment Received" in the Status Changes column for Draft to see the actions that are fired when the payment is received. +For now, we'll leave that as-is, but later on you may want to change the emails that Commerce sends when an order is paid. You can find those by clicking on "Payment Received" in the Status Changes column for Draft, to see the actions that are fired when the payment is received. You'll see two email actions are configured here, a confirmation email to the customer, and the order notification to the merchant. By clicking on the name (or "Edit Status Change Action" in the Actions menu), you can see the subject, recipient, and content configuration for each. By default these use templates, but you may need to tweak the recipient email on the order notification to merchant. ## Setting up Payment Methods -In the installation, a "Dummy Payment" was automatically created. This uses the [manual payment gateway](../Payment_Methods/Manual) which just marks the order as paid. If you want to add other payment method options, you can do that at Configuration > Payment Methods. +In the installation, a "Dummy Payment" was automatically created. This uses the [manual payment gateway](../Payment_Methods/Manual) which just marks the order as paid. If you want to add [other payment method options](../Payment_Methods), you can do that at **Configuration » Payment Methods**. ## Setting up Delivery Types & Shipping Methods -Depending on what you will be selling, you may or may not need to tweak the delivery types in Configuration > Delivery Types. For basic shops where every sold product fits in the same type of box or is distributed digitally in the same way, you will only need a single delivery delivery type. - -If you have different types of products, for example a combination of ebooks and physical books, you'll need to create an additional delivery type. +Depending on what you will be selling, you may or may not need to tweak the [delivery types](../Delivery_Types) in **Configuration » Delivery Types**. For basic shops, where every sold product fits in the same type of box or is distributed digitally in the same way, you will only need a single delivery type. -It's best to set up delivery types for distinct ways of getting the customer their order. While you'll create a delivery type for an ebook and another one for a physical books, you wont typically need a different delivery type if you also sell t-shirts, as those are delivered the same way as a book. +If you have different types of products however, for example a combination of ebooks and physical books, you'll need to create an additional delivery type. -For now, we'll only use the default "Standard Shipping" delivery type. You can edit the delivery type to make the shipping step required or never shown, depending on your requirements. In the default shipping step mode of "Depends", the shipping step is only shown in the checkout if there are 2 or more shipping methods available for an order. +As a way of determining if you need different delivery types, consider whether or not the way a product is delivered to the customer. While you'll create a delivery type for an ebook and another one for a physical books, you wont typically need a different delivery type if you also sell t-shirts, as those are delivered the same way as a book. If you use different fulfillment partners or warehouses, different delivery types can also be useful if that distinction is clear to the customer. -Next, go to Configuration > Shipping Methods. You'll have a free shipping method already from the installation, that's assigned to the Standard Shipping delivery type we just saw in Configuration > Delivery Types. +For now, we'll stick with the the default "Standard Shipping" delivery type. You can edit the delivery type to make the shipping step required or never shown, depending on your requirements. In the default shipping step mode of "Depends", the shipping step is only shown in the checkout if there are 2 or more shipping methods available for an order. -If you created extra delivery types, you'll also need to create additional shipping methods for each. +Next, navigate to **Configuration » Shipping Methods**. You'll already have a free shipping method from the setup, which is assigned to the Standard Shipping delivery type we just saw in **Configuration » Delivery Types**. If you created extra delivery types, you'll also need to create additional shipping methods for each. -To help with testing, you can choose to set the Free Shipping method to a minimum order total of €50 by editing it (click on its name in the grid) and setting "Min. Order Total" at the bottom to 5000 ($50). And then create another shipping method of type "Standard Shipping Method" that costs $7,50 for orders with a "Max. Order Total" of 5000 ($50). +To help with testing, you can choose to set the Free Shipping method to a minimum order total of $50 by editing it (click on its name in the grid) and setting "Min. Order Total" at the bottom to 5000 ($50). And then create another shipping method of type "Standard Shipping Method" that costs $7,50 for orders with a "Max. Order Total" of 5000 ($50). -_» Tip:_ Prices in Commerce are configured in cents, but you'll see the formatted price when you remove focus from the field. +**» Tip:** Prices in Commerce are configured in cents, but you'll see the formatted price when you remove focus from the field. ![Setting up some shipping methods](../../images/gettingstarted/shipping.jpg) ## Setting up Currencies -The most common currencies for modmore customers will have already been created for you in the installation, but if you want to change the formatting or decide which one is used, head over to Configuration > Currencies. +The most common currencies have already been created for you in the installation, but if you want to change the formatting, or set which one to use, navigate to **Configuration » Currencies**. -Click on the currency name or choose Edit Currency in the actions menu to change the formatting options. In the Actions menu you can also choose _Set as Default_ to change the default currency. +Click on the currency name or choose Edit Currency in the actions menu to change the formatting options. In the Actions menu you can also choose _Set as Default_ to change the default currency. For Euro, some countries prefer to use the comma instead of the dot for the decimal separator. Click on Euro and switch out the values for "Decimal Point" and "Thousands Separator" to tweak that. ![The standard currencies](../../images/gettingstarted/currencies.jpg) -If you need to add a currency that is not included in Commerce by default, [this site has a comprehensive list of the ISO4217 codes and formatting to use](https://www.thefinancials.com/Default.aspx?SubSectionID=curformat). +If you need to add a currency that is not included in Commerce by default, [this site has a comprehensive list of the ISO4217 codes and formatting to use](https://www.thefinancials.com/Default.aspx?SubSectionID=curformat). The ISO codes are important to get right for certain payment providers. + +Use a different currency often? Let us know, maybe we can save you some time in the future by including it in the standard installation. [Learn more about currencies here](../Currencies). ## Setting up Tax Groups -Next up, create a tax group under Configuration > Tax Groups. Give it a name that describes the **type** of tax, not the actual rate to charge. For example you could have "Standard" and "Food", but you should not name them "21%" or "9%". +Next up, create a tax group under **Configuration » Tax Groups**. Give it a name that describes the **type** of tax, not the actual rate to charge. For example you could have "Standard Tax" and "Food", but you would not, typically, name them "21%" or "9%". + +After creating the tax group, choose **Manage Tax Rules**, in the Actions menu. -After creating the tax group, choose Manage Tax Rules in the Actions menu. +What the tax rules should be exactly depends on your jurisdiction and what you're selling, and to who. In many cases there is a tax rate that applies to local customers, and one (or more) for international customers. [The taxes documentation](../Taxes) explains in more detail how you can configure different rates and rules, but for now let's keep it simple, and add a simple singular tax rate that applies to every purchase. -What the tax rules should be exactly depends on your jurisdiction and what you're selling, and to two. In many cases there is a tax rate that applies to local customers, and one (or more) for international customers. [The taxes documentation](../Taxes) explains in more detail how you can configure different rates and rules, but for now let's keep it simple, and add a simple singular tax rate that applies to every purchase. +Click **Add Tax Rule**. Give it a priority of 1, set "Field name" to "country", and "Condition" to "Always". Leave the Rate Provider set to _Manual Tax Rate_. Save. -Click Add Tax Rule. Give it a priority of 1, set "Field name" to "country", and "Condition" to "Always". Leave the Rate Provider set to Manual Tax Rate. +After saving the rule, a new section _Rate Provider Options_ will be show. There you can enter the tax rate you want to charge, for example 21, give it a Tax Key like "STANDARD-NL", and a name that is shown to customers like `21% VAT` or `Standard VAT`. Save again. -When you save the tax rule, a new section "Rate Provider Options" will be shown. Enter the tax rate you want to charge, for example 21, give it a Tax Key like "STANDARD-NL", and a name that is shown to customers like "21% VAT" or "Standard VAT". Save again. +If you want to add more tax rules for different rates, repeat this process. The priority determines the order that the tax rules will be evaluated from top-to-bottom in the grid, so set the conditions so that the lowest priority number is the most specific, and eventually fall back to an "Always" condition with the highest priority number. When using conditions that depend on customer information that is not yet be available, the rule is ignored, so keep that in mind. -(If you want to add more tax rules, repeat this process. The priority determines in what order the tax rules will be evaluated, from top-to-bottom in the grid, so set the conditions so that the lowest priority number is the most specific, and eventually fall back to an "Always" condition with the highest priority number.) +When creating products, you'll select the tax group to use for that specific product. Or, if only one tax group is configured, it is selected for you automatically. ## Some final System Settings -Now that you've explored all parts of the configuration in the Commerce Dashboard, there are a few more system settings you may want to consider tweaking. These can be found by going to System (cog icon in the manager) > System Settings, and choosing "Commerce" in the first filter (namespace). +Now that you've explored the configuration in the Commerce Dashboard, there are a few more system settings you may want to consider tweaking. These can be found by going to System (cog icon in the manager) » System Settings, and choosing "Commerce" in the first filter (namespace). - There are some settings related to the account step in the checkout. [Read more about how to configure them for what result in the Users documentation](../Users) - The `commerce.default_weight_unit` setting is useful to configure before creating products. It defaults to `kg`, but virtually all weight units are supported. - Don't want to see the beta warning? Disable `commerce.show_beta_warning`. -- The E-mail & Notifications settings are useful to configure some default email options, like an image to use as image header with `commerce.email_header_url`. +- The E-mail & Notifications settings are useful to configure some default email options, like an image to use as image header with `commerce.email_header_url`. Other email options are configured through the [status workflow](../Statuses) - In the Taxes area, set the `commerce.tax_calculation` to `inclusive` if you want product prices to be treated as having taxes included in them, instead of adding taxes on top of it. +- The resource related settings should already be (partially) configured for you as part of the setup, but you may want to tweak your `login_resource` ([how to setup your login page](../Users/Login_Resource)), `register_resource` ([how to setup your registration page](../Users/Register_Resource)), and `shop_resource` settings. You can ignore the _Resource Product_ settings for now. ## Up next: set up your Product Catalog -Now that the most important configuration is in place, it's time to start [setting up your products](Product_Catalog)! +Now that the most important configuration is in place, let's start [setting up your products](Product_Catalog)! diff --git a/en/01_Commerce/v1/01_Getting_Started/03_Product_Catalog.md b/en/01_Commerce/v1/01_Getting_Started/03_Product_Catalog.md index 73c84ad7..70f2aa0a 100644 --- a/en/01_Commerce/v1/01_Getting_Started/03_Product_Catalog.md +++ b/en/01_Commerce/v1/01_Getting_Started/03_Product_Catalog.md @@ -1,7 +1,160 @@ -This page is still waiting to be written! It will explain the different ways you can manage products and what decisions you'll need to make about that, and will then guide you through creating your first products and related templates. +_This document assumes [Commerce was downloaded and installed with the default options](index) and that [you've gone through the basic configuration](Configuration)._ -For now, [see the Product Catalog reference](../Product_Catalog). +Now that your basic shop configuration is in place, and you have an idea of the different pieces that are involved, let's start talking about the actual products and your catalog. -## Next: setting up your Cart & Checkout +[TOC] -What good are products if you can't buy them? [Lets work on the cart and checkout next](Cart_Checkout). +## Products and the Catalog + +In Commerce there is a distinction between the _products_ and the _catalog_. This may seem a bit odd, but is by design to enable more flexible and powerful shops. + +**Products** are simple representations of an item that you sell. A product could be "Rainbow shirt in size M", which has its SKU, price, weight, stock, etc. Commerce doesn't natively have variations within products: each unique option you have in your warehouse is a unique product. + +The **Catalog** is how your products are organised and presented to customers. This contains your products, of course, but may also cover reviews, categories, filters, product videos and galleries, brands, etc. + +**Commerce focuses primarily on the products**. You'll use a selection of tools, not necessarily tools provided by modmore, to build out the catalog exactly how you want it to work. Then you'll hook in the products in Commerce. + +## Laying out your product catalog + +For most MODX shops, we recommend building the catalog based around resources. For example, you might use: + +- [Collections](https://modx.com/extras/package/collections) as categories. Collections show up in the resource tree like regular resources, except it hides regular child resources from the tree. That allows you to have hundreds or even thousands of resources, without overloading the tree. Each child resource would be a product page. +- [Tagger](https://modx.com/extras/package/tagger) and/or [mSearch2](https://en.modstore.pro/packages/ecommerce/msearch2) to allow a customer to drill down products within categories based on values you store in TVs on each product page. +- [pdoTools](https://modx.com/extras/package/pdotools) to list resources and to generate menus. + +These tools allow you to use MODX in the same way you would for normal sites. + +To hook up Commerce, you will then use what we call the **Products TV** or **Matrix TV** on your product pages. These are template variable types that ship with Commerce that let you maintain either a list or a matrix of products that are associated with the page. + +Imagine this resource structure: + +- Clothing + - Shirts + - Design A + - Design B + - Design C + - Jeans + - Design D + - Design E + - Design F + +All designs will have a set of sizes that are available for selection on that product page. You will manage the general catalog page through the resources, while the sizes are the products in Commerce, with their own price and stock. The Products TV lets you manage a one-dimensional list of product variations. + +**About the Product Matrix:** + +> The Product Matrix TV works in a similar way to the Products TV, but instead of a one-dimensional list, it lets you define 2 properties and products are automatically created for the intersections of those properties. This is useful for a variety of use cases, but it's a bit more complex to get started with. If this is your first time working with Commerce, we'd recommend first getting to grips with the system using the Products TV. When you have that working, you can [learn more about the product matrix](../Product_Catalog/Product_Matrix) for more powerful product management. + +So let's start building. Install Collections, and create a sample resource structure for your shop, perhaps based on the sample above. Make sure to create a template for your categories, and a template for your product resources. + +### Product Template + +Create a [Products TV](../Product_Catalog/Products_TV) with name `products`, and assign it to your product template. Use it to create some products on one of your product pages. (For example, on your _Design A_ resource, add `Design A - M`, `Design A - L` and `Design A - XL` and give them different prices.) + +In your product template, add `[[*products]]` to see the comma separated list of product IDs for that specific product page. We can turn that into a list of product variations with the [get_product](../Snippets/get_product) and [get_products](../Snippets/get_products) snippets. + +Start by making the first product in the list available as the main product information: + +````html +[[!commerce.get_product? &product=`[[*products]]` &toPlaceholders=`product_info`]] +```` + +Now we can use placeholders prefixed with `product_info` to get any of the product fields. For example, we may show the resource title followed by the SKU and price of the first product, and then the main resource content that may include a product description: + +````html +[[!commerce.get_product? &product=`[[*products]]` &toPlaceholders=`product_info`]] +

[[*longtitle:default=`[[*pagetitle]]`]]

+

SKU: [[!+product_info.sku]] | Price: [[!+product_info.price_formatted]]

+[[*content]] +```` + +We'll also need to add the ability to select from the different products, and submit that to the cart. [There are 2 different form structures you can use](../Product_Catalog/Add_to_Cart_Form), we'll use the single product variation. + +````html +
+ + + +
+ + +
+
+ + +
+ + +
+```` + +The `product_as_select` chunk: + +````html + +```` + +What's important to note here is that we have 3 required fields we're submitting to the cart: + +- `add_to_cart` with value 1 to indicate we want to add something +- `product` with the ID of a Commerce Product that we want to add. In the example above, this is a ` + + + + + + + + or find out more + + +```` + +The add to cart form in this listing is slightly different because we used the quantity as a hidden field, and we're using the get_product snippet with a `&field` property to get specific product information. + +## Going beyond + +With the basic structure in place, you can now start building your catalog. Perhaps you want to add related products, show the add to cart form only if there's sufficient stock, or add more TVs to your products for highlights or product specs. The sky is the limit! + +You can also try the [product matrix](../Product_Catalog/Product_Matrix), instead of the products tv. The matrix is a more powerful way of managing products that combines 2 product attributes or properties into automatically generated products. You will need to make changes to your template and add to cart form to get that one hooked up, which is a little more complex than the Products TV due to its different structure. + +## Next: customising your Cart & Checkout + +The cart and checkout should already be up and running, but you can customise a great deal. [Lets work on the cart and checkout, and look at theming them with Twig](Cart_Checkout). diff --git a/en/01_Commerce/v1/01_Getting_Started/04_Cart_Checkout.md b/en/01_Commerce/v1/01_Getting_Started/04_Cart_Checkout.md index 4db0de80..b8160ac9 100644 --- a/en/01_Commerce/v1/01_Getting_Started/04_Cart_Checkout.md +++ b/en/01_Commerce/v1/01_Getting_Started/04_Cart_Checkout.md @@ -1,8 +1,171 @@ -This page is still waiting to be written! It will explain the how you can customise your cart and checkout, and also explain some relevant modules. +--- +title: Customising the Cart & Checkout +--- -For now see [theming](../Front-end_Theming). +_This document assumes [Commerce was downloaded and installed with the default options](index), that [you've gone through the basic configuration](Configuration), and [started building your Product Catalog to the point of having a functional add-to-cart form](Product_Catalog)._ + +At this point you should have added your first product to the cart. Congrats! + +Now we're going to start changing the cart and checkout to fit your shop. There's a lot you can do, some which will require more technical skills than others, so we'll go over a few common things to do. + +It's important to note that, technically speaking, the cart and checkout are part of the same system. That's why you'll also see cart shown as a step in the checkout. + +[TOC] + +## Exploring the Checkout Steps + +By default, Commerce shows all of the following steps: + +- **Cart**, usually on a separate page, where the customer manages the items they're buying, can add coupon codes, and chooses to checkout +- **Account**, offers the customer to either login or to continue as a guest +- **Address**, asks the customer to enter their shipping and billing address information. +- **Shipping**, asks the customer to choose a shipping method +- **Payment**, requests payment from the customer +- **Thank you**, confirms the order was paid and the order is complete + +It's not currently supported* to change the order or functionality of these steps drastically, but there are various ways to make this fit your shop. We'll go over those options for each step. + +* Technically, it _is_ possible to change the checkout steps, but we strongly discourage that level of customisation and do not currently provide documentation or support for it. We may change the underlying system in the future which would break custom checkout processes. + +#### Cart step + +The cart step is always present. It's how you can add items to an order, and where the customer can make changes. With the Coupons module enabled, this also has the form to validate a coupon code. + +The cart is usually on its own resource (identified by the `commerce.cart_resource` system setting), which the Commerce installation will have created for you. You can change the MODX template and presentation of this page to your liking. + +Further customisation to the cart usually revolves around changing the design or templates; we'll get to how that works in a minute. + +#### Account step + +The account step is optional, shown by default. + +If the customer visiting this step is already logged in, the customer will be immediately redirected to the next step. + +If the customer is not logged in, there are 2 options shown. There's a simple login form ([which you'll need to set up to work with the Login snippet](../Users/Login_Resource) as that's not done automatically for you) and a link to a [registration page](../Users/Register_Resource), and a button that lets the customer continue as a guest, without an account. + +![Default checkout templates with accounts being optional.](../../images/users/account-optional.jpg) + +Other use cases for the account step are possible just by changing a few system settings: + +- To always require a user to be logged in, set the `commerce.checkout_requires_account` system setting to yes. This will replace the block to continue as guest with a notice that an account is required. + +- To skip the account step completely, set both the `commerce.checkout_requires_account` and `commerce.checkout_show_account_step` settings to `no`. The account step will be removed from checkout completely. + +#### Address step + +The address step is required. It's where the customer enters their shipping (and optionally billing) address. If the customer is logged in, the address step may show previously used addresses as an option to speed along the process. + +#### Shipping step + +The shipping step is optional. When shown, it will calculate how much it costs to ship with each of your configured [shipping methods](../Shipping_Methods), show them in a list, and ask the customer to choose. If there are products from multiple [delivery types](../Delivery_Types) in the order, the customer will be asked to choose a shipping method for each. + +Commerce automatically selects the first available shipping method as soon as the cart, to present the user with an accurate total as soon as possible. + +On each [delivery type](../Delivery_Types) you can choose what to do with the shipping step: + +- By default, the shipping step is set to "depends", which means it will only be shown if there is more than one matching shipping method for the order. +- When you set the shipping step to "required" on the delivery type, the shipping step is always shown, even with just one matching shipping method that has been pre-selected. +- When you set the shipping step to "never", it is always hidden, and the customer cannot change the shipping method from the pre-selected one. + +#### Payment step + +The payment step is required. It lists available payment methods, including the calculated fee if set. + +If the order total is zero because of a coupon, or all products being free, then the payment step is automatically skipped and the order marked as completed. + +If the total is not zero, but you do not intend to use online payments, you can create a payment method with the [Manual payment gateway](../Payment_Methods/Manual). That will mark the order as paid without the customer actually paying. + +If you'd like to implement a sort of "confirmation step" into the checkout, it's recommended to change the templating of the payment step to act as that instead. If you want to have a checkbox that requires customers to accept terms and conditions, enable the Accept Terms module. + +#### Thank you step + +When the customer visits the thank you page, the order is completed and their cart is emptied for future orders. + +## Design & templates + +You have full control over the design and templating of your site. This is still MODX, after all! + +For your [catalog](Product_Catalog) you'll mostly use your standard MODX templating. For the cart and the checkout, however, you'll use **Twig** templates, which are stored in files. + +The default templates can be found in `core/components/commerce/templates/default/` - these **will be overwritten** on upgrade, so don't edit them directly. + +Start by changing the `commerce.theme` system setting. Give it a name, for example `myshop`, and create a new directory under `core/components/commerce/templates/` with the same name. That's now your own theme directory, which is safe from upgrades. + +To change templates, you will now copy them from the `default` folder, and paste them into the same directory structure in your `myshop` directory. + +#### Hello world + +Let's try it by adding "Hello world" to our cart. + +Copy `core/components/commerce/templates/default/frontend/checkout/cart.twig` into your theme directory following the same structure, so place the copy in `core/components/commerce/templates/myshop/frontend/checkout/cart.twig`. + +(If you want to do this via the manager, change the `upload_files` system setting to include the `twig` extension.) + +The template looks something like this: + +````html +
+

+ {% if order.total_quantity != 1 %} + {{ lex('commerce.cart_header', { 'items': order.total_quantity }) }} + {% else %} + {{ lex('commerce.cart_header_single') }} + {% endif %} +

+ + {% include 'frontend/response-messages.twig' %} + + {% if items|length > 0 %} + {% include 'frontend/checkout/cart/items.twig' %} +
+
+ {% include 'frontend/checkout/cart/aside.twig' %} +
+
+ {% include 'frontend/checkout/cart/totals.twig' %} + +
+ + +
+
+
+ {% else %} +

{{ lex('commerce.cart.no_items_yet') }} {{ lex('commerce.cart.continue_shopping') }}

+ {% endif %} +
+```` + +Change the heading bit at the top to the following: + +````html +

+ Hi there! + {% if order.total_quantity != 1 %} + {{ lex('commerce.cart_header', { 'items': order.total_quantity }) }} + {% else %} + {{ lex('commerce.cart_header_single') }} + {% endif %} +

+```` + +If you visit your cart now, that should say `Hi there!` towards the top. + +#### More tweaking + +There's a few dozen templates you can tweak in the same way. Their naming are hopefully clear enough to indicate where they are used, and you may also come across `include` calls in some templates referencing other nested templates. + +You only have to copy the templates you want to change - all other templates will fall back to the `default` template. + +In general, all templates in the `frontend` and `emails` directories are safe to change. Make sure to keep IDs and input names the same, to ensure things keep working as expected. Class names are less critical, but in some cases (payment method templates especially), you may want to keep those as-is. + +**Note**: It's recommended to **not** edit any of the `admin` templates, those are used in the dashboard and we do not currently make an effort to preserve backwards compatibility in those templates. This means that if you copy or change the admin templates, and upgrade Commerce, you may end up with a broken dashboard. + +#### CSS, lexicons, custom theme folders, and more + +See [theming](../Front-end_Theming) for more options to change the design and templates. There are many different things you can do. ## Next -When you have your shop functional, let's end this tutorial with some notes about [extending Commerce](Extending_Commerce). +When you have your shop functional, it's time to talk about the [next steps](Next_Steps). diff --git a/en/01_Commerce/v1/01_Getting_Started/05_Extending_Commerce.md b/en/01_Commerce/v1/01_Getting_Started/05_Extending_Commerce.md deleted file mode 100644 index d5b29a83..00000000 --- a/en/01_Commerce/v1/01_Getting_Started/05_Extending_Commerce.md +++ /dev/null @@ -1,3 +0,0 @@ -This page is still waiting to be written! It will explain some available extensions from modmore and third parties, and point you to our [developer documentation](../Developer) that explains the different technical possibilities. - - diff --git a/en/01_Commerce/v1/01_Getting_Started/05_Next_Steps.md b/en/01_Commerce/v1/01_Getting_Started/05_Next_Steps.md new file mode 100644 index 00000000..e56f72df --- /dev/null +++ b/en/01_Commerce/v1/01_Getting_Started/05_Next_Steps.md @@ -0,0 +1,21 @@ +If you've made it here, you've accomplished quite a lot. + +- [You went through the configuration and modules in Commerce](Configuration) +- [You decided, and made a head-start, on building out your catalog](Product_Catalog) +- [You tweaked the cart and checkout, and learned about templating with Twig](Cart_Checkout) + +Well done! + +This is where our getting started documentation, for now, ends. We've tried to give you the insight and tools to find your way through the dashboard and the most common customisation. There is a lot to learn about Commerce still, but you'll learn that while building out your shop. + +Depending on your use case, the following sections of the documentation are recommended reading material: + +- [Read about currency support](../Currencies) +- [Learn more about the Products TV approach to building a catalog](../Product_Catalog/Products_TV) +- For information about tweaking emails that get sent, [see order messages](../Orders/Messages) +- The [status workflow](../Statuses) is a powerful tool for automating parts of your fulfillment processes, and is also where you configure **emails that get sent to users and the merchant**. +- [Read the Frequently Asked Questions](https://support.modmore.com/collection/48-commerce) to learn more about common issues and questions we get. Chances are, what you want to know is already explained there in detail. + +If you're a developer looking to extend Commerce, take a look at our [developer documentation](../Developer). That contains a lot of information about how core parts of Commerce work, and how you can interact with that. + +If you need help with Commerce, please do get in touch. You can use the support widget in the bottom right of the page (might not show up if use adblockers), or simply email support@modmore.com. We're here to help. diff --git a/en/01_Commerce/v1/01_Getting_Started/index.md b/en/01_Commerce/v1/01_Getting_Started/index.md index ba300ffe..ba3bcdca 100644 --- a/en/01_Commerce/v1/01_Getting_Started/index.md +++ b/en/01_Commerce/v1/01_Getting_Started/index.md @@ -12,15 +12,15 @@ On this page: ## Downloading Commerce -First of all you'll need to install Commerce in your MODX installation. Commerce is available from the modmore.com [package provider](https://www.modmore.com/about/package-provider/), so you'll need to create an [api key](https://www.modmore.com/account/api-keys/) and add that to your MODX site to get started. +First of all you'll need to install Commerce in your MODX installation. Commerce is available from the modmore.com [package provider](https://modmore.com/about/package-provider/), so you'll need to create an [api key](https://modmore.com/account/api-keys/) and add that to your MODX site to get started. -**» Note:** If you're new to modmore and haven't worked with our package provider before, [learn more about how that works here](https://www.modmore.com/about/package-provider/). It's a one-time set up to access all our extras. +**» Note:** If you're new to modmore and haven't worked with our package provider before, [learn more about how that works here](https://modmore.com/about/package-provider/). It's a one-time set up to access all our extras. -In order to install Commerce, you will need to have a license. [Licenses are available for €299](https://www.modmore.com/commerce/pricing/), but free development licenses are available to use while you're building the shop. +In order to install Commerce, you will need to have a license. [Licenses are available for €299](https://modmore.com/commerce/pricing/), but free development licenses are available to use while you're building the shop. -To use a [free development license](https://www.modmore.com/free-development-licenses/), make sure that your MODX installation is installed on a domain that matches the free development licenses whitelist. This means you should be on a domain like `localhost`, `site.local`, `dev.site.com`, or a similar pattern. [The full list of supported domains can be found here](https://www.modmore.com/free-development-licenses/#faq_109). If you're unable (or unwilling) to use a domain that is approved for free licenses, you can also use a paid license and transfer that to the live domain later. +To use a [free development license](https://modmore.com/free-development-licenses/), make sure that your MODX installation is installed on a domain that matches the free development licenses whitelist. This means you should be on a domain like `localhost`, `site.local`, `dev.site.com`, or a similar pattern. [The full list of supported domains can be found here](https://modmore.com/free-development-licenses/#faq_109). If you're unable (or unwilling) to use a domain that is approved for free licenses, you can also use a paid license and transfer that to the live domain later. -When you have your [API Key](https://www.modmore.com/account/api-keys/) set up as a package provider in your MODX site, open the modmore.com package provider by clicking the arrow on the _Download Extras_ button (at Extras > Installer), choosing _Select a Provider_ in the menu, and choosing modmore.com in the window. +When you have your [API Key](https://modmore.com/account/api-keys/) set up as a package provider in your MODX site, open the modmore.com package provider by clicking the arrow on the _Download Extras_ button (at Extras > Installer), choosing _Select a Provider_ in the menu, and choosing modmore.com in the window. Find Commerce in the provider under Premium Extras > Commerce and choose Download. @@ -41,21 +41,21 @@ The installation will automatically set up the most important aspects of Commerc This is what it creates: - A basic [status workflow](../Statuses), covering the draft, processing and completed statuses, with the necessary status changes to send emails to the customer and merchant. -- A [shipping method](../Shipping_Methods) that provides free shipping in development. Even if you do not need shipping methods for your shop, you'll always need to have at least one method set up to complete the checkout process. +- A [delivery type](../Delivery_Types) and [shipping method](../Shipping_Methods) that provides free shipping in development. Even if you do not need shipping methods for your shop, you'll always need to have at least one method set up to complete the checkout process. - A [manual payment method](../Payment_Methods/Manual) that marks the order as paid without any money transfering hands for testing. - A set of [currencies](../Currencies), along with the proper subunits, formatting, alphanumeric and numeric codes. It will also set the currency you choose as the system default. -- A new resource with the [commerce.cart snippet](../Snippets/cart) to act as the cart. It will be created in the root of the web context, and the `commerce.cart_resource` system setting will be updated to point to it. -- A new resource with the [commerce.checkout snippet](../Snippets/checkout) which will hold the checkout process. It will be created in the root of the web context, and the `commerce.checkout_resource` system setting will be updated to point to it. +- A new resource with the [commerce.cart snippet](../Snippets/cart) to act as the cart. It will be created in the root of the web context, with your default template, and the `commerce.cart_resource` system setting will be updated to point to it. +- A new resource with the [commerce.checkout snippet](../Snippets/checkout) which will hold the checkout process. It will be created in the root of the web context, with your default template, and the `commerce.checkout_resource` system setting will be updated to point to it. Once these standard options are created, the installation will no longer offer these options when you reinstall or update Commerce to prevent duplications. If you want to recreate the standard currencies or status workflow, you will need to truncate the relevant tables in your database before Commerce will offer them as options. You will of course be able of changing every standard configuration after the installation. -The installation also verifies if your server meets the most important [requirements](../Requirements), including the MODX and PHP versions. Additional requirements (like serving the checkout over HTTPS) are checked when you want to enable live mode. +The installation also verifies if your server meets the most important [requirements](../Requirements), including the MODX and PHP versions. Additional requirements (like serving the checkout over HTTPS) are checked in the Configuration Checklist, in the Commerce dashboard, when you're looking at switching to live mode. ## Exploring Commerce -If the installation was successful, you're ready to start exploring the Commerce Dashboard. Refresh the manager, and find it under Extras » Commerce. +If the installation was successful, you're ready to start exploring the **Commerce Dashboard**. Refresh the manager, and find it under **Extras » Commerce**. [Start exploring the Commerce Configuration »](Configuration) diff --git a/en/01_Commerce/v1/02_Product_Catalog/Add_to_Cart_Form.md b/en/01_Commerce/v1/02_Product_Catalog/Add_to_Cart_Form.md index 73bd4468..78dd2458 100644 --- a/en/01_Commerce/v1/02_Product_Catalog/Add_to_Cart_Form.md +++ b/en/01_Commerce/v1/02_Product_Catalog/Add_to_Cart_Form.md @@ -1,8 +1,10 @@ -To add a product to the cart, you'll need to submit the product record ID (not the catalog ID) to the cart page. There are two variations supported, one for multiple products, and the other for single products. +To add a product to the cart, you'll need to submit the product record ID (not the resource ID) to the cart page. There are two form variations supported, one for multiple products, and the other for single products. + +[TOC] ## Single Products Form -With the single products form only one product can be added to the cart per request. As the structure of the form is a little easier than the multiple products form, it is easier to use this when providing different products as variations in your catalog. +With the single products form only one product can be added to the cart per request. As the structure of the form is a little easier than the multiple products form, it is easier to use this when providing different products as variations in your catalog. The form includes: - an `add_to_cart` hidden input with value 1, this is used to trigger the add to cart logic. @@ -13,30 +15,30 @@ The form includes:
- + - - + +
```` -Alpha note: support for the single products form was added in 0.3.3. +The `[[%commerce.add_to_cart]]` lexicon was added in v0.12; in older versions you may need to hardcode your submit text. ## Multiple Products Form -To add multiple products, you need to provide a `add_to_cart` value and a `products` array. The products array is provided as `product id => [options]`, for example `products[123][quantity] = 5`. +To add multiple products in a single submit action, you need to provide a `add_to_cart` value and a `products` array. The products array is provided as `product id => [options]`, for example `products[123][quantity] = 5`. -In a form, that looks somewhat like this. Replace `123` with the ID of your product. +In a form, that looks somewhat like this. Replace `123` with the ID of your product. ```` html
- + - - + +
```` @@ -44,15 +46,17 @@ Note that these two form structures cannot be mixed. The `products[id][quantity] ## Adding custom fields to the order item -Commerce (as of 0.11) supports simple custom fields using the [Item Data Module](../Modules/Cart/ItemData.md). The module allows you to define what field names to accept from the user, and then you can start sending those fields along with the add to cart request. This is great for user comments or simple product variations that have no impact on stock. +Commerce (as of 0.11) supports simple custom fields using the [Item Data Module](../Modules/Cart/ItemData.md). The module allows you to define what field names to accept from the user, and then you can start sending those fields along with the add to cart request. This is great for user comments or simple product variations that have no impact on stock. [See the Item Data Module documentation](../Modules/Cart/ItemData.md) for instructions on how to set that up. ## AJAX -You can also add products to the cart using AJAX. Just serialize the form values, and POST those values to the cart page with an XMLHttpRequest. Instead of HTML, you'll get JSON back. +You can also add products to the cart using AJAX. Just serialize the form values, and POST those values to the cart page with an XMLHttpRequest. Instead of HTML, you'll get JSON back. -For example the following jQuery snippet can be used to progressively enhance add to cart forms with AJAX. +> When using `window.fetch` or other ways of sending an ajax request except jQuery, **you must specify either the `X-Requested-With=XMLHttpRequest` or `Accept=application/json` (v1.3+) header** to trigger the JSON mode. + +For example the following jQuery snippet can be used to progressively enhance add to cart forms with AJAX. ```` html + +``` + +This service can be imported with the [Matomo service YAML +file](../yaml/consentfriend_matomo.yml) + +### Google Analytics + +| Setting | Value | +|-------------------------|----------------------------------------------------------------------------------------| +| Code Section | HEAD | +| Active | No | +| Default | No | +| Required | No | +| Opt Out | No | +| Only Once | Yes | +| Contextual Consent Only | No | +| Cookies | Cookie: _ga
Path: ''
Domain: ''
Cookie: '/^_ga.*$/'
Path: ''
Domain: '' | + +This service uses one MODX system or context setting in the default code. The +setting has to be created by yourself: + +| Schlüssel | Wert | +|---------------------|---------------------| +| google_analytics_id | Google Analytics ID | + +#### Code + +``` + + +``` + +#### Callbacks + +#### On Init + +``` + function (opts) { + window.dataLayer = window.dataLayer || []; + window.gtag = function(){ + dataLayer.push(arguments); + } + gtag('consent', 'default', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied'}); + } +``` + +#### On Accept + +``` + function (opts) { + window.dataLayer = window.dataLayer || []; + window.gtag = function(){ + dataLayer.push(arguments); + } + gtag('consent', 'update', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'granted'}); + } +``` + +#### On Decline + +``` + function (opts) { + window.dataLayer = window.dataLayer || []; + window.gtag = function(){ + dataLayer.push(arguments); + } + gtag('consent', 'update', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied'}); + } +``` + +This service can be imported with the [Google Analytics service YAML +file](../yaml/consentfriend_googleAnalytics.yml) + +### Google AdSense + +| Setting | Value | +|-------------------------|-------| +| Code Section | BODY | +| Active | No | +| Default | No | +| Required | No | +| Opt Out | No | +| Only Once | No | +| Contextual Consent Only | No | + +#### Code + +``` + +``` + +This service can be imported with the [Google AdSense service YAML +file](../yaml/consentfriend_googleAdSense.yml) + +### Google Fonts + +| Setting | Value | +|-------------------------|-------| +| Code Section | HEAD | +| Active | No | +| Default | No | +| Required | No | +| Opt Out | No | +| Only Once | No | +| Contextual Consent Only | No | + +#### Code + +``` + +``` + +This service can be imported with the [Google Fonts service YAML +file](../yaml/consentfriend_googleFonts.yml) + +### Cloudflare + +| Setting | Value | +|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Active | No | +| Default | No | +| Required | Yes | +| Opt Out | No | +| Only Once | No | +| Contextual Consent Only | No | +| Cookies | Cookie: _cflb
Path: ''
Domain: ''
Cookie: _cf_bm
Path: ''
Domain: ''
Cookie: _cfduid
Path: ''
Domain: ''
Cookie: cf_ob_info
Path: ''
Domain: ''
Cookie: 'cf_use_ob cookie'
Path: ''
Domain: '' | + +This service can be imported with the [Cloudflare service YAML +file](../yaml/consentfriend_cloudflare.yml) + +### YouTube + +| Setting | Value | +|-------------------------|---------------------------------------| +| Active | No | +| Default | No | +| Required | No | +| Opt Out | No | +| Only Once | No | +| Contextual Consent Only | No | +| Cookies | Cookie: abc
Path: ''
Domain: '' | + +This service can be imported with the [YouTube service YAML +file](../yaml/consentfriend_youtube.yml) + +### Google reCAPTCHA + +| Setting | Value | +|-------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Active | No | +| Default | No | +| Required | No | +| Opt Out | No | +| Only Once | No | +| Contextual Consent Only | No | +| Cookies | Cookie: IDE
Path: ''
Domain: ''
Cookie: 1P_JAR
Path: ''
Domain: ''
Cookie: ANID
Path: ''
Domain: ''
Cookie: CONSENT
Path: ''
Domain: ''
Cookie: NID
Path: ''
Domain: ''
Cookie: DVacd
Path: ''
Domain: '' | + +#### Callbacks + +##### On Toggle + +``` + function(consent, service) { + var buttons = document.body.querySelectorAll('input[data-name="' + service.name + '"],button[data-name="' + service.name + '"]'), index; + for (index = 0; index < buttons.length; index++) { + buttons[index].disabled = !consent; + } + } +``` + +This service can be imported with the [Google reCAPTCHA service YAML +file](../yaml/consentfriend_googleRecaptcha.yml) + +### Facebook Pixel + +| Setting | Value | +|-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| Code Section | BODY | +| Active | No | +| Default | No | +| Required | No | +| Opt Out | No | +| Only Once | No | +| Contextual Consent Only | No | +| Cookies | Cookie: xs
Path: ''
Domain: ''
Cookie: wd
Path: ''
Domain: ''
Cookie: spin
Path: ''
Domain: ''
Cookie: c_user
Path: ''
Domain: ''
Cookie: locale
Path: ''
Domain: ''
Cookie: datr
Path: ''
Domain: ''
Cookie: fr
Path: ''
Domain: ''
Cookie: presence
Path: ''
Domain: ''
Cookie: sb
Path: ''
Domain: '' | + +#### Code + +``` + + +``` + +This service can be imported with the [Facebook Pixel service YAML +file](../yaml/consentfriend_facebookPixel.yml) + +### Google Tag Manager + +| Setting | Value | +|-------------------------|-------| +| Code Section | HEAD | +| Active | No | +| Default | No | +| Required | No | +| Opt Out | No | +| Only Once | No | +| Contextual Consent Only | No | + +#### Code + +``` + +``` + +#### Callbacks + +#### On Init + +``` + function (opts) { + // initialization code here (will be executed only once per page-load) + window.dataLayer = window.dataLayer || []; + window.gtag = function () { + dataLayer.push(arguments); + } + gtag('consent', 'default', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied'}); + gtag('set', 'ads_data_redaction', true); + } +``` + +#### On Accept + +``` + function (opts) { + // we notify the tag manager about all services that were accepted. You can define + // a custom event in GTM to load the service if consent was given. + for (let k of Object.keys(opts.consents)) { + if (opts.consents[k]) { + let eventName = 'consentfriend-' + k + '-accepted'; + dataLayer.push({'event': eventName}); + } + } + // if consent for Google Analytics was granted we enable analytics storage + if (opts.consents['googleAnalytics']) { + console.log('Google analytics usage was granted!'); + gtag('consent', 'update', {'analytics_storage': 'granted'}); + } + // if consent for Google Ads was granted we enable ad storage + if (opts.consents['googleAdSense']) { + console.log('Google ads usage was granted!'); + gtag('consent', 'update', {'ad_storage': 'granted'}); + } + } +``` + +#### On Decline + +``` + function (opts) { + // we notify the tag manager about all services that were declined. You can define + // a custom event in GTM to unload the service if consent was denied. + window.dataLayer = window.dataLayer || []; + window.gtag = function () { + dataLayer.push(arguments) + } + gtag('consent', 'default', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied'}) + gtag('set', 'ads_data_redaction', true) + } +``` + +This service can be imported with the [Google Tag Manager service YAML +file](../yaml/consentfriend_googleTagManager.yml) + +### Google Maps + +| Setting | Value | +|-------------------------|-------| +| Active | No | +| Default | No | +| Required | No | +| Opt Out | No | +| Only Once | No | +| Contextual Consent Only | No | + +This service can be imported with the [Google Maps service YAML +file](../yaml/consentfriend_googleMaps.yml) diff --git a/en/02_ConsentFriend/v1/02_Functionality/03_Contextual_Consent.md b/en/02_ConsentFriend/v1/02_Functionality/03_Contextual_Consent.md new file mode 100644 index 00000000..70e49b45 --- /dev/null +++ b/en/02_ConsentFriend/v1/02_Functionality/03_Contextual_Consent.md @@ -0,0 +1,22 @@ +--- +title: Contextual Consent +--- + +Contextual consent allows the website to obtain the consent of the users on +place. This is used to hide embedded YouTube videos and display a placeholder +with a consent button inside. + +This function can be extended with the service setting 'Contextual Consent +Only'. If this setting is activated, the service cannot be directly activated +globally with the 'Accept All' workflow in the consent modal. The service is +still hidden by a placeholder, but a second button is displayed which allows the +user to activate the service globally. + +The contextual consent feature cannot be disabled, but the consent placeholder +can be hidden by the following css rule: + +```css +div[data-type="placeholder"] { + display: none; +} +``` diff --git a/en/02_ConsentFriend/v1/02_Functionality/Google_Tag_Manager.md b/en/02_ConsentFriend/v1/02_Functionality/Google_Tag_Manager.md new file mode 100644 index 00000000..3508be39 --- /dev/null +++ b/en/02_ConsentFriend/v1/02_Functionality/Google_Tag_Manager.md @@ -0,0 +1,26 @@ +--- +title: Google Tag Manager +--- + +You can integrate ConsentFriend with the Google Tag Manager (GTM) quite easy and +control consents for Google Analytics with ConsentFriend via the GTM. The demo +callback scripts in the googleTagManager service already contain the necessary +code for this. + +First, change the googleAnalytics service and delete the code block there. This +also applies to other existing and newly defined services that you want to +control via the GTM. You only need to list the cookies that these services set. + +Now create a Google Analytics tag in the GTM web UI. As a trigger, create a +[custom event trigger](https://support.google.com/tagmanager/answer/7679219) +named `consentfriend-googleAnalytics-accepted`. This will ensure that GTM only +loads the Google Analytics service if the user has given consent for it via +ConsentFriend. And that's it! + +ConsentFriend now manages GTM and ensures that only services that the user has +given consent for via ConsentFriend are loaded. + +> Important! To add another service via GTM, first enable or create a service in +ConsentFriend and simply define a custom event trigger of the form +`consentfriend-[service-name]-accepted`, where `[service-name]` is the name of the +service in the ConsentFriend configuration. diff --git a/en/02_ConsentFriend/v1/02_Functionality/Google_reCAPTCHA.md b/en/02_ConsentFriend/v1/02_Functionality/Google_reCAPTCHA.md new file mode 100644 index 00000000..9a7cf3c3 --- /dev/null +++ b/en/02_ConsentFriend/v1/02_Functionality/Google_reCAPTCHA.md @@ -0,0 +1,168 @@ +--- +title: Google reCAPTCHA +--- + +To disable the automatic loading and execution of the reCAPTCHA script, you need +to change, i.e. the recaptchav3_html chunk with the following code: + +``` + + + + +``` + +Since the order of execution of the javascripts when activated by Klaro! is not +clearly defined, the method `grecaptcha.ready` has to be called from a method +that is executed after loading the reCAPTCHA script with the onload attribute. +Otherwise you may get an `Uncaught ReferenceError: grecaptcha is not defined` +error in the browser console and reCAPTCHA will not work in this case. + +### Disable the inputs + +The forms secured by reCAPTCHA can be modified with a callback function based on +the approval status of the reCAPTCHA service. The following code is predefined +in the demo data in the onToggle callback from the reCAPTCHA service: + +``` +function(consent, service) { + var buttons = document.body.querySelectorAll('input[data-name="' + service.name + '"],button[data-name="' + service.name + '"]'), index; + for (index = 0; index < buttons.length; index++) { + buttons[index].disabled = !consent; + } +} +``` + +This code disables all inputs/buttons with `data-name="googleRecaptcha"`, when +no consent is given for this service and enables the inputs/buttons after the +consent is available. + +### Disable the submit + +Another option is to disable the submit button of the form and display a modal +window to enable the reCAPTCHA service if needed. is displayed. Below are +different examples of the onToggle callback. + +#### jQuery/Bootstrap 5: + +**onToggle Code** + +``` +function(consent, service) { + var button = $('button[data-name="' + service.name + '"], input[type="submit"][data-name="' + service.name + '"]'); + button.css('display', 'inline-block'); + if (!consent) { + button.on('click', function(event) { + var recaptchaModal = new bootstrap.Modal(document.getElementById('recaptchaModal')); + recaptchaModal.show(); + event.preventDefault(); + }); + } else { + button.off('click'); + } +} +``` + +**Code for the modal window** + +``` + +``` + +#### Javascript/Tailwind CSS + +**onToggle Code** + +``` +function(consent, service) { + window.consentFriend = window.consentFriend || {}; + window.consentFriend.recaptcha = consent; + window.consentFriend.recaptchaModal = document.getElementById('recaptcha-modal') + window.consentFriend.recaptchaButtons = document.body.querySelectorAll('input[data-name="' + service.name + '"],button[data-name="' + service.name + '"]'); + if (window.consentFriend.recaptchaModal && window.consentFriend.recaptchaButtons) { + if (!window.consentFriend.recaptchaListeners) { + document.getElementById('recaptcha-modal-change').addEventListener('click', function () { + window.consentFriend.recaptchaModal.classList.add('hidden'); + klaro.show(); + }); + document.getElementById('recaptcha-modal-close').addEventListener('click', function () { + window.consentFriend.recaptchaModal.classList.add('hidden'); + }); + } + var index; + for (index = 0; index < window.consentFriend.recaptchaButtons.length; index++) { + var button = window.consentFriend.recaptchaButtons[index]; + button.style.display = 'inline-block'; + button.disabled = false; + if (!window.consentFriend.recaptchaListeners) { + button.addEventListener('click', function (evt) { + if (!window.consentFriend.recaptcha) { + evt.preventDefault(); + window.consentFriend.recaptchaModal.classList.remove('hidden'); + } + }); + } + } + window.consentFriend.recaptchaListeners = true; + } +} +``` + +**Code for the modal window** + +``` + +``` diff --git a/en/02_ConsentFriend/v1/02_Functionality/Youtube_Videos.md b/en/02_ConsentFriend/v1/02_Functionality/Youtube_Videos.md new file mode 100644 index 00000000..42a29b2b --- /dev/null +++ b/en/02_ConsentFriend/v1/02_Functionality/Youtube_Videos.md @@ -0,0 +1,13 @@ +--- +title: YouTube Videos +--- + +To disable the automatic loading and execution of the YouTube videos, you have +to modify i.e. the iframe code with the following code: + +``` +~m', + '', + $input +); +``` + +Feel free to create your own output filter for other external services. + +## Is it possible to use Google Consent Mode v2 with ConsentFriend? + +Yes, the consent mode v2 can be set with ConsentFriend for Google Analytics. It +is now built into the default Google Analytics service configuration. In already +existing installations you can install the new code by importing the [Google +Analytics service YAML file](yaml/consentfriend_googleAnalytics.yml) or just +add the +[callbacks](https://docs.treehillstudio.de/en/consentfriend/02_Functionality/02_Default_Services/#callbacks) +on your own. diff --git a/en/02_ConsentFriend/v1/img/black.png b/en/02_ConsentFriend/v1/img/black.png new file mode 100644 index 00000000..80b99c58 Binary files /dev/null and b/en/02_ConsentFriend/v1/img/black.png differ diff --git a/en/02_ConsentFriend/v1/img/dark.png b/en/02_ConsentFriend/v1/img/dark.png new file mode 100644 index 00000000..d8cb45d0 Binary files /dev/null and b/en/02_ConsentFriend/v1/img/dark.png differ diff --git a/en/02_ConsentFriend/v1/img/dashboard-widget.png b/en/02_ConsentFriend/v1/img/dashboard-widget.png new file mode 100644 index 00000000..d6c757de Binary files /dev/null and b/en/02_ConsentFriend/v1/img/dashboard-widget.png differ diff --git a/en/02_ConsentFriend/v1/img/default.png b/en/02_ConsentFriend/v1/img/default.png new file mode 100644 index 00000000..609d726b Binary files /dev/null and b/en/02_ConsentFriend/v1/img/default.png differ diff --git a/en/02_ConsentFriend/v1/img/light.png b/en/02_ConsentFriend/v1/img/light.png new file mode 100644 index 00000000..bf957e49 Binary files /dev/null and b/en/02_ConsentFriend/v1/img/light.png differ diff --git a/en/02_ConsentFriend/v1/img/white.png b/en/02_ConsentFriend/v1/img/white.png new file mode 100644 index 00000000..142450c5 Binary files /dev/null and b/en/02_ConsentFriend/v1/img/white.png differ diff --git a/en/02_ConsentFriend/v1/index.md b/en/02_ConsentFriend/v1/index.md new file mode 100644 index 00000000..2d41c61c --- /dev/null +++ b/en/02_ConsentFriend/v1/index.md @@ -0,0 +1,28 @@ +--- +title: ConsentFriend +description: Documentation for ConsentFriend, a premium consent management platform for MODX by Treehill Studio. +--- + +[ConsentFriend](https://modmore.com/consentfriend/) is a simple but powerful +consent management platform for MODX. It acts as a privacy and security tool, +that controls the usage of third-party services on your website to protect the +frontend users. + +ConsentFriend disables third-party services and displays a consent management +window on the website. With this consent management window, the website user +can accept various third-party services. Afterwards the accepted services are +enabled on the page without a reload of the page. That way ConsentFriend +prepares a compliance with GDPR/DSGVO on the website and helps the site admin to +setup the consent management in an easy way. + +It is a perfect solution for website operators, that have to use third-party +frontend services on a MODX website. Since those services are able to collect +personal data, the service usage has to be fully transparent and compliant. + +## Recommended Reading + +- [Installation](01_Installation.md) +- [Functionality](02_Functionality/01_Introduction.md) +- [Custom Manager Page](03_Custom_Manager_Page/index.md) + + diff --git a/en/02_ConsentFriend/v1/yaml/consentfriend_all.yml b/en/02_ConsentFriend/v1/yaml/consentfriend_all.yml new file mode 100644 index 00000000..d49cea5d --- /dev/null +++ b/en/02_ConsentFriend/v1/yaml/consentfriend_all.yml @@ -0,0 +1,395 @@ +package: consentfriend +services: + - name: consentFriend + essential: 1 + title: '' + description: '' + code: '' + code_section: 1 + callback: '' + active: true + default: false + required: true + opt_out: false + only_once: false + contextual_consent_only: false + cookies: + - cookie: consentfriend + path: '' + domain: '' + sortindex: 0 + purposes: functional + - name: session + essential: 1 + title: '' + description: '' + code: '' + code_section: 1 + callback: '' + active: true + default: false + required: true + opt_out: false + only_once: false + contextual_consent_only: false + cookies: + - cookie: PHPSESSID + path: '' + domain: '' + sortindex: 1 + purposes: functional + - name: matomo + essential: 0 + title: '' + description: '' + code: | + + + code_section: 1 + callback: '' + active: false + default: false + required: false + opt_out: false + only_once: true + contextual_consent_only: false + cookies: + - cookie: '/^matomo_.*$/i' + path: '' + domain: '' + - cookie: '/^_pk_.*$/' + path: '' + domain: '' + sortindex: 2 + purposes: performance + - name: googleAnalytics + essential: 0 + title: '' + description: '' + code: | + + + code_section: 0 + callback: '' + on_accept: | + function (opts) { + console.log('accept'); + window.dataLayer = window.dataLayer || []; + window.gtag = function(){ + dataLayer.push(arguments); + } + gtag('consent', 'update', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'granted'}); + } + on_init: | + function (opts) { + console.log('init'); + window.dataLayer = window.dataLayer || []; + window.gtag = function(){ + dataLayer.push(arguments); + } + gtag('consent', 'default', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied'}); + } + on_decline: | + function (opts) { + console.log('decline'); + window.dataLayer = window.dataLayer || []; + window.gtag = function(){ + dataLayer.push(arguments); + } + gtag('consent', 'update', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied'}); + } + active: false + default: false + required: false + opt_out: false + only_once: true + contextual_consent_only: false + cookies: + - cookie: _ga + path: '' + domain: '' + - cookie: '/^_ga.*$/' + path: '' + domain: '' + sortindex: 3 + purposes: performance + - name: googleAdSense + essential: 0 + title: '' + description: '' + code: | + + code_section: 1 + callback: '' + active: false + default: false + required: false + opt_out: false + only_once: false + contextual_consent_only: false + cookies: { } + sortindex: 4 + purposes: advertising + - name: googleFonts + essential: 0 + title: '' + description: '' + code: '' + code_section: 0 + callback: '' + active: false + default: false + required: false + opt_out: false + only_once: false + contextual_consent_only: false + cookies: { } + sortindex: 5 + purposes: styling + - name: cloudflare + essential: 0 + title: '' + description: '' + code: '' + code_section: 1 + callback: '' + active: false + default: false + required: true + opt_out: false + only_once: false + contextual_consent_only: false + cookies: + - cookie: _cflb + path: '' + domain: '' + - cookie: _cf_bm + path: '' + domain: '' + - cookie: _cfduid + path: '' + domain: '' + - cookie: cf_ob_info + path: '' + domain: '' + - cookie: 'cf_use_ob cookie' + path: '' + domain: '' + sortindex: 6 + purposes: security + - name: youtube + essential: 0 + title: '' + description: '' + code: '' + code_section: 1 + callback: '' + active: false + default: false + required: false + opt_out: false + only_once: false + contextual_consent_only: false + cookies: + - cookie: abc + path: '' + domain: '' + sortindex: 7 + purposes: marketing + - name: googleRecaptcha + essential: 0 + title: '' + description: '' + code: '' + code_section: 1 + callback: |- + function(consent, service) { + var buttons = document.body.querySelectorAll('input[data-name="' + service.name + '"],button[data-name="' + service.name + '"]'), index; + for (index = 0; index < buttons.length; index++) { + buttons[index].disabled = !consent; + } + } + active: false + default: false + required: false + opt_out: false + only_once: false + contextual_consent_only: false + cookies: + - cookie: IDE + path: '' + domain: '' + - cookie: 1P_JAR + path: '' + domain: '' + - cookie: ANID + path: '' + domain: '' + - cookie: CONSENT + path: '' + domain: '' + - cookie: NID + path: '' + domain: '' + - cookie: DVacd + path: '' + domain: '' + sortindex: 8 + purposes: security + - name: facebookPixel + essential: 0 + title: '' + description: '' + code: | + + + code_section: 1 + callback: '' + active: false + default: false + required: false + opt_out: false + only_once: false + contextual_consent_only: false + cookies: + - cookie: xs + path: '' + domain: '' + - cookie: wd + path: '' + domain: '' + - cookie: spin + path: '' + domain: '' + - cookie: c_user + path: '' + domain: '' + - cookie: locale + path: '' + domain: '' + - cookie: datr + path: '' + domain: '' + - cookie: fr + path: '' + domain: '' + - cookie: presence + path: '' + domain: '' + - cookie: sb + path: '' + domain: '' + sortindex: 9 + purposes: marketing + - name: googleTagManager + essential: 0 + title: '' + description: '' + code: | + + code_section: 0 + callback: '' + on_accept: | + function (opts) { + // we notify the tag manager about all services that were accepted. You can define + // a custom event in GTM to load the service if consent was given. + for (let k of Object.keys(opts.consents)) { + if (opts.consents[k]) { + let eventName = 'consentfriend-' + k + '-accepted'; + dataLayer.push({'event': eventName}); + } + } + // if consent for Google Analytics was granted we enable analytics storage + if (opts.consents['googleAnalytics']) { + console.log('Google analytics usage was granted!'); + gtag('consent', 'update', {'analytics_storage': 'granted'}); + } + // if consent for Google Ads was granted we enable ad storage + if (opts.consents['googleAdSense']) { + console.log('Google ads usage was granted!'); + gtag('consent', 'update', {'ad_storage': 'granted'}); + } + } + on_init: | + function (opts) { + // initialization code here (will be executed only once per page-load) + window.dataLayer = window.dataLayer || []; + window.gtag = function () { + dataLayer.push(arguments); + } + gtag('consent', 'default', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied'}); + gtag('set', 'ads_data_redaction', true); + } + on_decline: | + function (opts) { + // we notify the tag manager about all services that were declined. You can define + // a custom event in GTM to unload the service if consent was denied. + window.dataLayer = window.dataLayer || []; + window.gtag = function () { + dataLayer.push(arguments) + } + gtag('consent', 'default', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied'}) + gtag('set', 'ads_data_redaction', true) + } + active: false + default: false + required: false + opt_out: false + only_once: false + contextual_consent_only: false + cookies: { } + sortindex: 10 + purposes: marketing + - name: googleMaps + essential: 0 + title: '' + description: '' + code: '' + code_section: 0 + callback: null + on_accept: null + on_init: null + on_decline: null + active: true + default: false + required: false + opt_out: false + only_once: false + contextual_consent_only: false + cookies: { } + sortindex: 11 + purposes: styling diff --git a/en/02_ConsentFriend/v1/yaml/consentfriend_cloudflare.yml b/en/02_ConsentFriend/v1/yaml/consentfriend_cloudflare.yml new file mode 100644 index 00000000..f480408b --- /dev/null +++ b/en/02_ConsentFriend/v1/yaml/consentfriend_cloudflare.yml @@ -0,0 +1,31 @@ +package: consentfriend +services: + - name: cloudflare + title: '' + description: '' + code: '' + code_section: 1 + callback: '' + active: false + default: false + required: true + opt_out: false + only_once: false + contextual_consent_only: false + cookies: + - cookie: _cflb + path: '' + domain: '' + - cookie: _cf_bm + path: '' + domain: '' + - cookie: _cfduid + path: '' + domain: '' + - cookie: cf_ob_info + path: '' + domain: '' + - cookie: 'cf_use_ob cookie' + path: '' + domain: '' + purposes: security diff --git a/en/02_ConsentFriend/v1/yaml/consentfriend_consentFriend.yml b/en/02_ConsentFriend/v1/yaml/consentfriend_consentFriend.yml new file mode 100644 index 00000000..2718f26e --- /dev/null +++ b/en/02_ConsentFriend/v1/yaml/consentfriend_consentFriend.yml @@ -0,0 +1,19 @@ +package: consentfriend +services: + - name: consentFriend + title: '' + description: '' + code: '' + code_section: 1 + callback: '' + active: true + default: false + required: true + opt_out: false + only_once: false + contextual_consent_only: false + cookies: + - cookie: consentfriend + path: '' + domain: '' + purposes: functional diff --git a/en/02_ConsentFriend/v1/yaml/consentfriend_facebookPixel.yml b/en/02_ConsentFriend/v1/yaml/consentfriend_facebookPixel.yml new file mode 100644 index 00000000..ab26b6a5 --- /dev/null +++ b/en/02_ConsentFriend/v1/yaml/consentfriend_facebookPixel.yml @@ -0,0 +1,58 @@ +package: consentfriend +services: + - name: facebookPixel + title: '' + description: '' + code: | + + + code_section: 1 + callback: '' + active: false + default: false + required: false + opt_out: false + only_once: false + contextual_consent_only: false + cookies: + - cookie: xs + path: '' + domain: '' + - cookie: wd + path: '' + domain: '' + - cookie: spin + path: '' + domain: '' + - cookie: c_user + path: '' + domain: '' + - cookie: locale + path: '' + domain: '' + - cookie: datr + path: '' + domain: '' + - cookie: fr + path: '' + domain: '' + - cookie: presence + path: '' + domain: '' + - cookie: sb + path: '' + domain: '' + purposes: marketing diff --git a/en/02_ConsentFriend/v1/yaml/consentfriend_googleAdSense.yml b/en/02_ConsentFriend/v1/yaml/consentfriend_googleAdSense.yml new file mode 100644 index 00000000..c9441bb9 --- /dev/null +++ b/en/02_ConsentFriend/v1/yaml/consentfriend_googleAdSense.yml @@ -0,0 +1,17 @@ +package: consentfriend +services: + - name: googleAdSense + title: '' + description: '' + code: | + + code_section: 1 + callback: '' + active: false + default: false + required: false + opt_out: false + only_once: false + contextual_consent_only: false + cookies: { } + purposes: advertising diff --git a/en/02_ConsentFriend/v1/yaml/consentfriend_googleAnalytics.yml b/en/02_ConsentFriend/v1/yaml/consentfriend_googleAnalytics.yml new file mode 100644 index 00000000..a3e7b637 --- /dev/null +++ b/en/02_ConsentFriend/v1/yaml/consentfriend_googleAnalytics.yml @@ -0,0 +1,57 @@ +package: consentfriend +services: + - name: googleAnalytics + title: '' + description: '' + code: | + + + code_section: 0 + callback: '' + on_accept: | + function (opts) { + console.log('accept'); + window.dataLayer = window.dataLayer || []; + window.gtag = function(){ + dataLayer.push(arguments); + } + gtag('consent', 'update', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'granted'}); + } + on_init: | + function (opts) { + console.log('init'); + window.dataLayer = window.dataLayer || []; + window.gtag = function(){ + dataLayer.push(arguments); + } + gtag('consent', 'default', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied'}); + } + on_decline: | + function (opts) { + console.log('decline'); + window.dataLayer = window.dataLayer || []; + window.gtag = function(){ + dataLayer.push(arguments); + } + gtag('consent', 'update', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied'}); + } + active: false + default: false + required: false + opt_out: false + only_once: true + contextual_consent_only: false + cookies: + - cookie: _ga + path: '' + domain: '' + - cookie: '/^_ga.*$/' + path: '' + domain: '' + purposes: performance diff --git a/en/02_ConsentFriend/v1/yaml/consentfriend_googleFonts.yml b/en/02_ConsentFriend/v1/yaml/consentfriend_googleFonts.yml new file mode 100644 index 00000000..6225cec0 --- /dev/null +++ b/en/02_ConsentFriend/v1/yaml/consentfriend_googleFonts.yml @@ -0,0 +1,16 @@ +package: consentfriend +services: + - name: googleFonts + title: '' + description: '' + code: '' + code_section: 0 + callback: '' + active: false + default: false + required: false + opt_out: false + only_once: false + contextual_consent_only: false + cookies: { } + purposes: styling diff --git a/en/02_ConsentFriend/v1/yaml/consentfriend_googleMaps.yml b/en/02_ConsentFriend/v1/yaml/consentfriend_googleMaps.yml new file mode 100644 index 00000000..69242948 --- /dev/null +++ b/en/02_ConsentFriend/v1/yaml/consentfriend_googleMaps.yml @@ -0,0 +1,19 @@ +package: consentfriend +services: + - name: googleMaps + title: '' + description: '' + code: '' + code_section: 0 + callback: null + on_accept: null + on_init: null + on_decline: null + active: true + default: false + required: false + opt_out: false + only_once: false + contextual_consent_only: false + cookies: { } + purposes: styling diff --git a/en/02_ConsentFriend/v1/yaml/consentfriend_googleRecaptcha.yml b/en/02_ConsentFriend/v1/yaml/consentfriend_googleRecaptcha.yml new file mode 100644 index 00000000..3004ecf7 --- /dev/null +++ b/en/02_ConsentFriend/v1/yaml/consentfriend_googleRecaptcha.yml @@ -0,0 +1,40 @@ +package: consentfriend +services: + - name: googleRecaptcha + title: '' + description: '' + code: '' + code_section: 1 + callback: |- + function(consent, service) { + var buttons = document.body.querySelectorAll('input[data-name="' + service.name + '"],button[data-name="' + service.name + '"]'), index; + for (index = 0; index < buttons.length; index++) { + buttons[index].disabled = !consent; + } + } + active: false + default: false + required: false + opt_out: false + only_once: false + contextual_consent_only: false + cookies: + - cookie: IDE + path: '' + domain: '' + - cookie: 1P_JAR + path: '' + domain: '' + - cookie: ANID + path: '' + domain: '' + - cookie: CONSENT + path: '' + domain: '' + - cookie: NID + path: '' + domain: '' + - cookie: DVacd + path: '' + domain: '' + purposes: security diff --git a/en/02_ConsentFriend/v1/yaml/consentfriend_googleTagManager.yml b/en/02_ConsentFriend/v1/yaml/consentfriend_googleTagManager.yml new file mode 100644 index 00000000..c35f415a --- /dev/null +++ b/en/02_ConsentFriend/v1/yaml/consentfriend_googleTagManager.yml @@ -0,0 +1,63 @@ +package: consentfriend +services: + - name: googleTagManager + title: '' + description: '' + code: | + + code_section: 0 + callback: '' + on_accept: | + function (opts) { + // we notify the tag manager about all services that were accepted. You can define + // a custom event in GTM to load the service if consent was given. + for (let k of Object.keys(opts.consents)) { + if (opts.consents[k]) { + let eventName = 'consentfriend-' + k + '-accepted'; + dataLayer.push({'event': eventName}); + } + } + // if consent for Google Analytics was granted we enable analytics storage + if (opts.consents['googleAnalytics']) { + console.log('Google analytics usage was granted!'); + gtag('consent', 'update', {'analytics_storage': 'granted'}); + } + // if consent for Google Ads was granted we enable ad storage + if (opts.consents['googleAdSense']) { + console.log('Google ads usage was granted!'); + gtag('consent', 'update', {'ad_storage': 'granted'}); + } + } + on_init: | + function (opts) { + // initialization code here (will be executed only once per page-load) + window.dataLayer = window.dataLayer || []; + window.gtag = function () { + dataLayer.push(arguments); + } + gtag('consent', 'default', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied'}); + gtag('set', 'ads_data_redaction', true); + } + on_decline: | + function (opts) { + // we notify the tag manager about all services that were declined. You can define + // a custom event in GTM to unload the service if consent was denied. + window.dataLayer = window.dataLayer || []; + window.gtag = function () { + dataLayer.push(arguments); + } + gtag('consent', 'default', {'ad_storage': 'denied', 'ad_user_data': 'denied', 'ad_personalization': 'denied', 'analytics_storage': 'denied'}); + gtag('set', 'ads_data_redaction', true); + } + active: false + default: false + required: false + opt_out: false + only_once: false + contextual_consent_only: false + cookies: { } + purposes: marketing diff --git a/en/02_ConsentFriend/v1/yaml/consentfriend_matomo.yml b/en/02_ConsentFriend/v1/yaml/consentfriend_matomo.yml new file mode 100644 index 00000000..cde71e11 --- /dev/null +++ b/en/02_ConsentFriend/v1/yaml/consentfriend_matomo.yml @@ -0,0 +1,35 @@ +package: consentfriend +services: + - name: matomo + title: '' + description: '' + code: | + + + code_section: 1 + callback: '' + active: false + default: false + required: false + opt_out: false + only_once: true + contextual_consent_only: false + cookies: + - cookie: '/^matomo_.*$/i' + path: '' + domain: '' + - cookie: '/^_pk_.*$/' + path: '' + domain: '' + purposes: performance diff --git a/en/02_ConsentFriend/v1/yaml/consentfriend_session.yml b/en/02_ConsentFriend/v1/yaml/consentfriend_session.yml new file mode 100644 index 00000000..ebb0ef3c --- /dev/null +++ b/en/02_ConsentFriend/v1/yaml/consentfriend_session.yml @@ -0,0 +1,19 @@ +package: consentfriend +services: + - name: session + title: '' + description: '' + code: '' + code_section: 1 + callback: '' + active: true + default: false + required: true + opt_out: false + only_once: false + contextual_consent_only: false + cookies: + - cookie: PHPSESSID + path: '' + domain: '' + purposes: functional diff --git a/en/02_ConsentFriend/v1/yaml/consentfriend_youtube.yml b/en/02_ConsentFriend/v1/yaml/consentfriend_youtube.yml new file mode 100644 index 00000000..b3ef13e3 --- /dev/null +++ b/en/02_ConsentFriend/v1/yaml/consentfriend_youtube.yml @@ -0,0 +1,19 @@ +package: consentfriend +services: + - name: youtube + title: '' + description: '' + code: '' + code_section: 1 + callback: '' + active: false + default: false + required: false + opt_out: false + only_once: false + contextual_consent_only: false + cookies: + - cookie: abc + path: '' + domain: '' + purposes: marketing diff --git a/en/02_ContentBlocks/v1.x/-Fields.md b/en/02_ContentBlocks/v1.x/-Fields.md new file mode 100644 index 00000000..1e5bf67f --- /dev/null +++ b/en/02_ContentBlocks/v1.x/-Fields.md @@ -0,0 +1,5 @@ +--- +title: Fields (moved) +--- + +[This page has moved.](Fields) \ No newline at end of file diff --git a/en/02_ContentBlocks/v1.x/00_Layouts.md b/en/02_ContentBlocks/v1.x/00_Layouts.md index d8139178..3cbe7c54 100755 --- a/en/02_ContentBlocks/v1.x/00_Layouts.md +++ b/en/02_ContentBlocks/v1.x/00_Layouts.md @@ -2,6 +2,8 @@ In ContentBlocks you can use _Layouts_ to easily manage multi column content. Ea During installation you get the opportunity to install some basic Foundation and Bootstrap based layouts to get started quickly. +[TOC] + ## Managing Layouts To manage Layouts, find the Content Blocks component under the Extras menu and move to the Layouts tab. @@ -39,6 +41,12 @@ If you create a column with reference "main", your placeholder will be [[+main]] Any settings you define are also available as placeholder. If you add a setting with a reference of "class", the placeholder in your template will be [[+class]]. +Other available placeholders in Layout templates: + +- `[[+layout_title]]` (or `[[+title]]`); you can edit the layout title by clicking on the title on the canvas +- `[[+idx]]`, the index (position) of the layout +- `[[+unique_idx]]`, a unique index across all elements on the page (fields and layouts) + [![](https://assets.modmore.com/galleries/inline-418/2015/contentblocks_component_layout_template.png)](https://assets.modmore.com/galleries/inline-418/2015/contentblocks_component_layout_template.png) diff --git a/en/02_ContentBlocks/v1.x/01_Fields/Templates.md b/en/02_ContentBlocks/v1.x/01_Fields/Templates.md new file mode 100644 index 00000000..d7676453 --- /dev/null +++ b/en/02_ContentBlocks/v1.x/01_Fields/Templates.md @@ -0,0 +1,86 @@ +Field templates can be found by editing a [field in the ContentBlocks component](../Fields) and opening the Properties tab. + +[TOC] + +## Placeholders + +Templates use the standard MODX parser, and have access to a number of placeholders in the form of `[[+KEY]]`. + +Which placeholders exactly depend on the [input type](../Input_Types). In the ContentBlocks component you can hover over the "Template" label to see available placeholders for the selected input type in the tooltip. + +In most cases, you'll have at least a `[[+value]]` placeholder. Any field settings you add are also available as `[[+name_of_setting]]`. + +All field templates have access to a set of shared placeholders: + +- `[[+idx]]`, an incrementing index for the fields inside the current layout column. +- `[[+unique_idx]]`, a guaranteed to be unique incrementing index. This index number is incremented for each field or layout that is processed, nested layouts included, meaning the order is dependant on the exact page structure. You can **not** rely on two fields side-by-side being one index apart. +- `[[+layout_id]]`, the ID of the parent layout the field is inserted in. +- `[[+layout_column]]`, the string name of the column the field is inserted in. +- `[[+layout_idx]]`, an incrementing index for the position of the layout on the page. +- `[[+layout_title]]`, the title of the layout (user-editable by clicking on it in the interface); may be empty. +- `[[+field_type_idx]]`, an index (starting at 0) of which instance of this particular field. Useful in combination with the cbGetFieldContent snippet. (as of v1.14.0) + +It's also possible to access layout settings in field templates (as of v1.8.3). Those are available with the `layout_settings` prefix, for example: + +``` +[[+layout_settings.my_setting_key] +``` + +## Using @CHUNK templates + +If you'd like to use static elements, you can use chunks. The best way to do so is by using the `@CHUNK` syntax, which will pass all available placeholders into your chunk automatically. + +**Important to note: chunks are processed when rendering the page, rather than when saving it.** This means that using chunks in ContentBlocks comes at an extra performance penalty for the first (uncached) front-end request for a page. + +For example, define your template like this: + +```html +@CHUNK NameOfYourChunk +``` + +That will be parsed by ContentBlocks into a full chunk tag, like this: + +``` +[[$NameOfYourChunk? + &value=`Some Value` + &layout_id=`5` + &layout_column=`main` + ... +]] +``` + +(_This works exactly the same in layout templates._) + +## Using @FILE templates + +As of v1.11 `@FILE` templates are also supported. + +Unlike `@CHUNK` templates which don't get parsed until the front-end renders a resource, `@FILE` templates are parsed during the resource save so are more performant. You do however need to save the resource or rebuild all pages after making a change to a template file, similar to regular inline templates. + +The syntax is simply `@FILE path/to/file.ext`. There is no required extension, but `.tpl` or `.html` is suggested. + +**In order to use `@FILE`, you need to configure a media source and path first.** + +1. Create, if you don't already have one, a media source to hold the templates. We strongly recommend using one that has its base path set to a non-web-accessible location, such as `core/elements/`. +2. Set the `contentblocks.file_template_source` system setting to your media source. +3. Set the `contentblocks.file_template_path` system setting to a path inside that media source where ContentBlocks templates are located. To use the root of the media source, use `/`. By setting this to a value like `contentblocks` or `cb`, you can use it alongside other elements. + +After these steps, you can go to Extras > ContentBlocks to add the `@FILE` template to your fields or layouts. + +If the media source and/or path is not correct, your front-end will render the following: + +```html +

Failed processing template, please refer to the error log.

+``` + +The MODX error log will have a more detailed message telling you if the problem was loading the media source or the template file. If it can't find the file, it will log the full path to make debugging easier. + +(_This works exactly the same in layout templates._) + +## Using pdoTools' @FILE templates (@PDO_FILE) + +If you'd like to use Fenom templates, you can use @PDO_FILE in field and layout templates. This works exactly like a @FILE template like you're used to with pdoTools/Fenom, it just has a different prefix to differentiate between the built-in @FILE support. + +This was added in ContentBlocks 1.13, with special thanks to Joeke Kloosterman + + diff --git a/en/02_ContentBlocks/v1.x/01_Fields.md b/en/02_ContentBlocks/v1.x/01_Fields/index.md similarity index 76% rename from en/02_ContentBlocks/v1.x/01_Fields.md rename to en/02_ContentBlocks/v1.x/01_Fields/index.md index f2830b40..90c9d207 100755 --- a/en/02_ContentBlocks/v1.x/01_Fields.md +++ b/en/02_ContentBlocks/v1.x/01_Fields/index.md @@ -1,7 +1,11 @@ -Fields are implementation of an [Input Type](Input_Types) (such as _heading_ or _gallery_), which defines how the content added by an editor is turned into the markup. As input types often provide a number of other properties for defining how it works or what it can do, you can have multiple configurations of that with multiple fields of the same input type. +Fields are implementation of an [Input Type](../Input_Types) (such as _heading_ or _gallery_), which defines how the content added by an editor is turned into the markup. As input types often provide a number of other properties for defining how it works or what it can do, you can have multiple configurations of that with multiple fields of the same input type. To give a simple example, you may define "Note" and "Warning" fields so editors can add callout blocks into the content. These fields would both be a _textarea_ or _richtext_ input type, but because their template is different, they provide vastly different use cases and visual styles in the front-end. +[TOC] + +## Managing Fields + To manage fields, head over to Components and find the Content Blocks menu item. On the Fields tab, you can click _Add Field_, or right click a field and choose _Edit Field_ to open the field window. You'll find a number of tabs, which we'll go over in detail below, to help you manage your ContentBlocks fields. - General: used for managing the basic field information. @@ -16,10 +20,10 @@ To manage fields, head over to Components and find the Content Blocks menu item. On the General tab, you can edit the basic information for this field. That includes choosing the Input type, giving it a name, description and icon for in the _Add Content_ modal as well as defining the sort order. -- Input: a dropdown list with titles and descriptions of the currently existing [Input Types](Input_Types). This includes [custom inputs](Custom_Inputs/Developing_Custom_Inputs) as well as the built-in types. As soon as you choose an input type (Heading in the example), it will set the default icon for you and set some default properties in the Properties tab, but you are of course free to change this as you see fit. +- Input: a dropdown list with titles and descriptions of the currently existing [Input Types](../Input_Types). This includes [custom inputs](../Custom_Inputs/Developing_Custom_Inputs) as well as the built-in types. As soon as you choose an input type (Heading in the example), it will set the default icon for you and set some default properties in the Properties tab, but you are of course free to change this as you see fit. - Name: the name the editor will see in the _Add Content_ modal. If you have multiple fields for the same input, you will probably give them a more distinctive name, but we'll settle for just "Heading" here. - Description: an optional description to add to the popup in the Add Content modal for the editor. -- Icon: choose one of the many [included icons](Custom_Inputs/Icons), this is used in the _Add Content_ modal to quickly identify the field. +- Icon: choose one of the many [included icons](../Custom_Inputs/Icons), this is used in the _Add Content_ modal to quickly identify the field. - Sort Order: the order in which to show the fields is defined by the sort order value. Lower numbers go first. @@ -28,7 +32,7 @@ On the General tab, you can edit the basic information for this field. That incl [![](https://assets.modmore.com/galleries/inline-418/2015/contentblocks_component_field_properties.png)](https://assets.modmore.com/galleries/inline-418/2015/contentblocks_component_field_properties.png) -The properties tab consists input-specific properties. All inputs have a template, which typically has a `[[+value]]` placeholder but depending on the [input type](Input_Types) there can be more or different placeholders, templates and other properties. By hovering over the properties you will get a tooltip with more information about the property, which typically includes the available placeholders along with general instructions. +The properties tab consists input-specific properties. All inputs have a template, which typically has a `[[+value]]` placeholder but depending on the [input type](../Input_Types) there can be more or different placeholders, templates and other properties. By hovering over the properties you will get a tooltip with more information about the property, which typically includes the available placeholders along with general instructions. @@ -58,7 +62,7 @@ When fields are, based on the conditions, not allowed to be used, existing insta [![](https://assets.modmore.com/galleries/inline-418/2015/contentblocks_component_field_settings.png)](https://assets.modmore.com/galleries/inline-418/2015/contentblocks_component_field_settings.png) -Settings are, [just like Layout Settings](Layouts), configuration options that you can add to a field which the Editor can then change when adding content to it. Settings are added as placeholders to the field's template so you can easily pass, for example, a class or inline style to a fields template. In the image above we have defined a "Class" setting (which will fill the `[[class]]` placeholder in our template, defined on the Properties tab) with a select field type and a couple of values. +Settings are, [just like Layout Settings](../Layouts), configuration options that you can add to a field which the Editor can then change when adding content to it. Settings are added as placeholders to the field's template so you can easily pass, for example, a class or inline style to a fields template. In the image above we have defined a "Class" setting (which will fill the `[[class]]` placeholder in our template, defined on the Properties tab) with a select field type and a couple of values. There's also an option called _Expose Fields_. This option allows you to define how the setting is made available to the editor, which is one of the following: @@ -78,6 +82,7 @@ Clicking the cog symbol will open the "Headline Settings" modal (we named our fi ## More information... -- [Built-in input types](Input_Types) -- [Layouts](Layouts) -- [Custom input types](Custom_Inputs/Developing_Custom_Inputs) \ No newline at end of file +- [Field Templates](Templates) +- [Built-in input types](../Input_Types) +- [Layouts](../Layouts) +- [Custom input types](../Custom_Inputs/Developing_Custom_Inputs) \ No newline at end of file diff --git a/en/02_ContentBlocks/v1.x/02_Templates.md b/en/02_ContentBlocks/v1.x/02_Templates.md index c599e805..cde9ed97 100755 --- a/en/02_ContentBlocks/v1.x/02_Templates.md +++ b/en/02_ContentBlocks/v1.x/02_Templates.md @@ -4,6 +4,7 @@ Templates are available as of ContentBlocks v1.1. With Templates you can define The screenshots on this page were taken on Revolution 2.3, but this of course also works on 2.2. +[TOC] ## Creating a Template diff --git a/en/02_ContentBlocks/v1.x/03_Default_Templates.md b/en/02_ContentBlocks/v1.x/03_Default_Templates.md index 1bebd65b..b24b7c10 100755 --- a/en/02_ContentBlocks/v1.x/03_Default_Templates.md +++ b/en/02_ContentBlocks/v1.x/03_Default_Templates.md @@ -5,6 +5,7 @@ If you haven't worked with Templates before, be sure to [read more about Templat To manage your default templates, go to _Extras_ (or _Components_ pre-2.3) in the top navigation and choose ContentBlocks in the drop down. Open the Defaults tab. +[TOC] ## Rules diff --git a/en/02_ContentBlocks/v1.x/04_Categories.md b/en/02_ContentBlocks/v1.x/04_Categories.md new file mode 100644 index 00000000..a72671a7 --- /dev/null +++ b/en/02_ContentBlocks/v1.x/04_Categories.md @@ -0,0 +1,3 @@ +Categories in ContentBlocks allow you to group your fields, layouts and templates into logical sections. + +It's not required to use categories. Elements that are not assigned to a category will be in a virtual "Uncategorized" category at the bottom of the add content modals. \ No newline at end of file diff --git a/en/02_ContentBlocks/v1.x/04_Configuration.md b/en/02_ContentBlocks/v1.x/04_Configuration.md index 8dcf6a3e..699329c8 100755 --- a/en/02_ContentBlocks/v1.x/04_Configuration.md +++ b/en/02_ContentBlocks/v1.x/04_Configuration.md @@ -2,7 +2,7 @@ title: Configuration --- -Most configuration for ContentBlocks is done through the Component (and the [fields](Fields), [layouts](Layouts) and [templates](Templates) that makes available), however there are also a number of System Settings available that can be used to change the way ContentBlocks works. +Most configuration for ContentBlocks is done through the Component (through the [fields](Fields), [layouts](Layouts) and [templates](Templates) that makes available), however there are also a number of System Settings available that can be used to change the way ContentBlocks works. All of these settings are created automatically when installing ContentBlocks. They can also be added manually to Users, User Groups or Contexts to override their values for specific users or contexts. To do that, add a new setting with the mentioned key (including the `contentblocks.` prefix!) and the desired value. @@ -12,11 +12,11 @@ All of these settings are created automatically when installing ContentBlocks. T ### Accepted Resource Types (`contentblocks.accepted_resource_types`) -Comma separated list of the resource types ContentBlocks should be enabled on. There are built in resource types in MODX like modDocument, but other extras may also provide them in a way that ContentBlocks can support. This includes for example MoreGallery, [Collections](http://modx.com/extras/package/collections), [GoodNews](http://www.bitego.com/extras/goodnews) and [SimpleCart](https://www.modmore.com/simplecart/). +Comma separated list of the resource types ContentBlocks should be enabled on. There are built in resource types in MODX like modDocument, but other extras may also provide them in a way that ContentBlocks can support. This includes for example MoreGallery, [Collections](http://modx.com/extras/package/collections), [GoodNews](http://www.bitego.com/extras/goodnews) and [SimpleCart](https://modmore.com/simplecart/). For instructions about using ContentBlocks on custom resource types, please visit the [Custom Resources](Custom_Resources) documentation. -**Default:** `modDocument, mgResource, Article, CollectionContainer, GridContainer, GoodNewsResourceContainer, GoodNewsResourceMailing, scCategoryResource, scProductResource` +**Default:** `modDocument, MODX\Revolution\modDocument, mgResource, Article, Articles\Model\Article, CollectionContainer, Collections\Model\CollectionContainer, GridContainer, GoodNewsResourceContainer, GoodNewsResourceMailing, scCategoryResource, scProductResource, Location, Bitego\GoodNews\Model\GoodNewsResourceMailing, Bitego\GoodNews\Model\GoodNewsResourceContainer` ### Clear Cache after Rebuild (`contentblocks.clear_cache_after_rebuild`) @@ -26,7 +26,7 @@ When Rebuilding Content via the ContentBlocks component, you may find that the c ### Custom Icon Path (`contentblocks.custom_icon_path`) -If you'd like to use custom icons ([see the default set here](https://www.modmore.com/contentblocks/custom-inputs/icons/)), you can set the (server) path here. The {assets\_path} placeholder will be replaced with the full path to your assets directory. Also make sure to set the Custom Icon URL to match the path provided here. +If you'd like to use custom icons ([see the default set here](https://modmore.com/contentblocks/custom-inputs/icons/)), you can set the (server) path here. The {assets\_path} placeholder will be replaced with the full path to your assets directory. Also make sure to set the Custom Icon URL to match the path provided here. ### Custom Icon URL (`contentblocks.custom_icon_url`) @@ -38,10 +38,27 @@ When enabled ContentBlocks will load unminified assets to help debug issues. Typ ### Disabled (`contentblocks.disabled`) -When this setting is turned on, ContentBlocks will no longer be used. This setting in particular is useful to only selectively enable ContentBlocks per context, as you can disable ContentBlocks globally through this system setting, and then enable it on a specific context by adding a context setting with the same key. When this setting is turned on, ContentBlocks will no longer be used. This setting in particular is useful to only selectively enable ContentBlocks per context, as you can disable ContentBlocks globally through this system setting, and then enable it on a specific context by adding a context setting with the same key. -**Default:** `0 (false)` +**Default:** `0 (false)` (means ContentBlocks is enabled) + +#### Enable/Disable by template + +**To enable or disable ContentBlocks by template**, you previously needed to create a custom plugin to override the per-resource `contentblocks._isContentBlocks` flag in the properties. See the [example for whitelisting](https://support.modmore.com/article/73-how-can-contentblocks-be-enabled-on-specific-templates-only), and [example for blacklisting templates](https://support.modmore.com/article/72-how-can-contentblocks-be-disabled-on-specific-templates). Such a plugin is a flexible approach that will still work, and also allows you to go beyond simple template conditionals if needed. + +**As of ContentBlocks v1.10, you can also configure this through the template properties.** + +1. First decide if you want to _whitelist_ templates (in which case you disable ContentBlocks globally, and then enable it per-template), or _blacklist_ them (in which you enable ContentBlocks globally, but disable specific templates). Set the `contentblocks.disabled` system (or context) setting accordingly. +2. Edit the template you want to enable/disable. Navigate to the Properties tab. +3. Unlock the default properties by clicking the "Default Properties Locked" button in the grid. (While for snippets and plugins you would typically create a custom property set, that's not currently possible for templates.) +4. Create a new property with key `contentblocks.disabled` - please make sure to check your spelling. Set the value to 1 if you want to disallow ContentBlocks on this template, set the value to 0 (or an empty string) to allow it. +5. Repeat for other templates you are whitelisting/blacklisting. + +![Screenshot showing the Template Properties tab filled out with the contentblocks.disabled property.](img/template-property.jpg) + +This way of enabling/disabling ContentBlocks takes priority over the per-resource flag. Just like context-level restrictions, if ContentBlocks is disabled, it will not show up at all on the resource. + +[All ways of enabling or disabling ContentBlocks are summarised here.](https://support.modmore.com/article/71-can-i-enable-disable-contentblocks-system-wide-per-context-per-resource-or-based-on-other-factors) ### Hide Logo (`contentblocks.hide_logo`) diff --git a/en/02_ContentBlocks/v1.x/05_Cropping.md b/en/02_ContentBlocks/v1.x/05_Cropping.md new file mode 100644 index 00000000..5a02c993 --- /dev/null +++ b/en/02_ContentBlocks/v1.x/05_Cropping.md @@ -0,0 +1,77 @@ +ContentBlocks 1.8 and up come with an image cropper. It's off by default, but can be enabled by adding the crop configuration to an image field. + +The cropper lets the designer or developer define the different crop(s) that should be available, while the end user (editor) can select the part of the image to use for each crop. This can be restricted in size and aspect ratio. Cropped images are generated when saving the crop, so there is no performance penalty to using them in the frontend. + +[TOC] + +## Setting up Crops + +To set up crops, you'll edit an [image](Input_Types/Images) [field](Fields) and enter a specially formatted crop definition into the Crops property. + +The crop definition is a specially crafted string containing one or more crops, separated by the pipe symbol (`|`). + +Here's an example of what the setting might contain: + +`small:width=200,height=200,aspect=1|medium:width=500,aspect=0.7|large:height=750` + +The syntax uses a pipe symbol (`|`) to separate different crops. In the above example, we defined three different crops: small, medium and large. + +For each of the crops, the definition starts off with its **name**, followed by a colon (`:`) separating it from the crop **options**. + +The name is displayed to the user when editing an image, and also used for the placeholders with the field template. + +![Example of the image cropper](img/image-cropper.jpg) + +When hovering over an inserted image in the canvas, you can also see a preview of each crop. Clicking those will directly edit that specific crop in the cropper. + +![Previewing crops on an image field](img/crops-preview.gif) + +Options are separated by a comma (`,`) and are specified in the `key=value` format. There are currently four supported options: + +- **aspect**: the aspect ratio is the `width` of an image, divided by its `height`. A square image has an aspect ratio of `1`, while a landscape image has an aspect ratio `bigger than 1` and a portrait image has a aspect ratio of `smaller than 1`. To set the aspect ratio, add `aspect=1.3` where 1.3 is the ratio you want to enforce with a **period** as decimal sign. When no aspect ratio is defined, the user has the ability to select any type of rectangle. +- **width**: a width in pixels to limit the selected crop to. This does not restrict the size of the _selected region_, but it will make sure the generated image is at most that wide. +- **height**: a maximum height in pixels. As with the width, this does not restrict the size of the selectable region but only affects how the image is generated. + +The end-user does not _see_ these settings directly, however they do see the results. Their crop selection will be restricted to the aspect ratio you define and the image will be generated at the right size determined by the width and height. + +If an aspect ratio is set, or inferred by both the width and height being set, then the Aspect Ratio section will not be shown in the options sidebar. + +The resize fields will be disabled if the width or height is set. If the aspect ratio is set along with either the width or the height, then the other one is also disabled as there is no other possibility then the one calculated. + +If only one crop is specified, then the left sidebar to switch between crops will not be shown. + +## Updating your Field Template + +You'll probably want to display the crops in your front-end once they're generated. This can be done by using some new placeholders that are available in the template for your image field. + +The crop placeholders follow the format: `[[+crops.{CROP_NAME}.{CROP_VALUE_KEY}]]` where `{CROP_NAME}` is the name of the crop as it was defined in the Crops property on your field (for example _small_, _medium_ or _large_ in the earlier example), and `{CROP_VALUE_KEY}` is one of the below. + +- `url`: A fully qualified URL to the cropped image. For example `/assets/crops/small.ao451jds.filename.png`. +- `targetWidth`: the width of the cropped image in px. +- `targetHeight`: the height of the cropped image in px. +- `width` The width, in pixels, of the selection area on the source image, this is **not the crop width**. For example `200`. +- `height` The height, in pixels, of the selected area on the source image, this is **not the crop height**. For example `300` +- `x`, `y`: The coordinates (in pixels) of the selected (or automatically calculated) crop. `(x, y)` is the coordinate of the top left corner. + +So for example if your crop was called small, you could get the url for the cropped image with `[[+crops.small.url]]`, its width with `[[+crops.small.targetWidth]]` and the height with `[[+crops.small.targetHeight]]`. + +Using these placeholders, you can add your crops in the way you'd like them to appear in your imageTpl chunk! Perhaps using the picture element or simply to highlight different areas of an image. + +## Making crops more intuitive + +The default cropper accounts for multiple crops to be defined. If you only want to use one crop to act as the thumbnail, you can enable the `Open cropper automatically` field property and set the `Use crop for thumbnail` property to the key of your crop. That way, the crop will be used instead of the dynamically generated thumbnail in the manager, and the cropper will also show as soon as an image is added, prompting the user to select the part of the image that should be shown. + +## Crop Quality + +By default, crops are created at 90% quality. If you'd like smaller file sizes, or crisper images, you can use the following two system settings to change the quality. + +- For JPEG, set `contentblocks.crop_jpeg_quality` to a number between 1 and 100. +- For PNG, set `contentblocks.crop_png_compression` to a number between 1 and 10. + +The extension used is determined from the source image that is cropped. + +(_Note:_ These system settings were not automatically created by ContentBlocks until v1.8.2. Before that release, you may need to create the setting manually, but then they will work.) + +## Animated Crops + +ContentBlocks supports creating crops of animated .gif images. However, note that this will only work if the server has Imagick enabled for PHP. \ No newline at end of file diff --git a/en/02_ContentBlocks/v1.x/05_Input_Types/Dropdown.md b/en/02_ContentBlocks/v1.x/05_Input_Types/Dropdown.md index f5c5bcf6..050b80e0 100755 --- a/en/02_ContentBlocks/v1.x/05_Input_Types/Dropdown.md +++ b/en/02_ContentBlocks/v1.x/05_Input_Types/Dropdown.md @@ -26,11 +26,20 @@ Specify the options for the dropdown here. See the section _Defining the Options A value, which exists in the Drop-down Options, that should be preselected when the field is added to a page. +**Important:** If your default value is **empty**, the dropdown input will use the **first option**. + +### Search Enabled + +Available in ContentBlocks 1.12 and above, there is a new `Search Enabled` property. If enabled, it will include a typeahead/search +field on the dropdown that allows filtering the available options displayed. Disabled it any time to revert to a regular dropdown field. + ## Defining the Options The Dropdown input type needs to have a set of options configured via the field properties. The way these are defined is very flexible. -Here are the different formats which are supported. The _value_ is the actual value for a selection, and the _Displayed Value_ is what the editor sees in the dropdown. Both are also available in the field template. Each format is specified on a single line, separated by a line break (\\n). +Here are the different formats which are supported. The _value_ is the actual value for a selection, and the _Displayed Value_ is what the editor sees in the dropdown. Both are also available in the field template. + +Each format is specified on a single line, separated by a line break (\\n). - `value==Displayed Value` Simple static value definition. Note the use of the double equal signs, this is similar to how you would define template variables. @@ -47,6 +56,8 @@ Use the `@SNIPPET` binding to dynamically fill the dropdown with the output from These formats can be mixed and matched as needed. The official recommendation is to use the `value==Displayed Value` format predominantly. +**Important:** Do not use empty values, except for a first option if you must. ContentBlocks **does not differentiate** between when an empty value was selected, and when no value is set yet, which means that empty values cause ContentBlocks to always fall back to the default value. If you have an empty value that is not the first value, that means it will never be pre-selected. (This may change in 2.0.) + ### Dynamic options with @SNIPPET With the @SNIPPET binding you can execute a snippet to fill the dropdown. The snippet needs to return either a JSON encoded array, or a list of options following the above format, separated by a line break (\\n). @@ -103,3 +114,4 @@ $options = array( return implode("\n", $options); ```` + diff --git a/en/02_ContentBlocks/v1.x/05_Input_Types/Images.md b/en/02_ContentBlocks/v1.x/05_Input_Types/Images.md index 8e255eff..8ff1c0af 100644 --- a/en/02_ContentBlocks/v1.x/05_Input_Types/Images.md +++ b/en/02_ContentBlocks/v1.x/05_Input_Types/Images.md @@ -16,6 +16,11 @@ Both input types work the same aside from the addition of the title field. - Images, obviously! - Image-based icons in a call to action, especially useful when combined with other fields in a [Repeater](Repeater). +## Cropping + +As of v1.8, the Image field supports cropping. This is configured on the field properties. [Read more about the image cropper in ContentBlocks](../Cropping) + + ## Related Settings See the [Configuration](../Configuration) documentation for a description of the available settings. diff --git a/en/02_ContentBlocks/v1.x/05_Input_Types/Multi-Select.md b/en/02_ContentBlocks/v1.x/05_Input_Types/Multi-Select.md new file mode 100755 index 00000000..13115472 --- /dev/null +++ b/en/02_ContentBlocks/v1.x/05_Input_Types/Multi-Select.md @@ -0,0 +1,77 @@ +The multi-select input type is an extended version of the dropdown input type. This means that any of the +[dropdown configuration options](https://docs.modmore.com/en/ContentBlocks/v1.x/Input_Types/Dropdown.html) also apply to the multi-select version. + +Multi-select settings are also available and function similarly to the select setting, but also include +configurable templates and output separators. + +The difference between the multi-select, and the dropdown input or select setting is... you guessed it... you can +select more than one value at a time! + +- **Key**: multi_select +- **Template Placeholders**: `[[+value]]` +- **Requirements**: ContentBlocks 1.12 + +## On this page + +[TOC] + +## Example + +[ ![Multi-Select](../img/multi-select-input-type.png)](../img/multi-select-input-type.png) + +## Features at a Glance + + - Select multiple values. + - Available as both an input type and a setting. + - Includes all the same remote and local configuration options as the [dropdown input type](https://docs.modmore.com/en/ContentBlocks/v1.x/Input_Types/Dropdown.html). + - Typeahead / search functionality. Type into the multi-select field to filter the options shown in the dropdown. + - Customisable via a template field, input options, output separator and defaults. + +## Available Properties + +### Template + +Just like other input types, the template field contains a `[[+value]]` placeholder. The important distinction to note +here is that the template field represents a single value that is selected. So you can add HTML markup here, and it +will be repeated in the output for each value that is selected by the user. See the Output Separator section below to +add something between each one. + +Normally, leaving the `[[+value]]` placeholder there will be all you need. However, if you're interested in getting a +bit more complex, have a look at this image: + +[ ![Multi-Select](../img/multi-select-field-properties.png)](../img/multi-select-field-properties.png) + +In the above example, we're hard-coding the product ids and product names in the Drop-down Options field using the `==` syntax, +then in the template, we're calling a [commerce.get_product](https://docs.modmore.com/en/Commerce/v1/Snippets/get_product.html) +snippet that takes the multi-select `[[+value]]` and parses it through a chunk called `product_tpl`, which contains +placeholders for all the product values, and HTML markup to display it. + +So in this example, it's acting a bit like a [repeater field](https://docs.modmore.com/en/ContentBlocks/v1.x/Input_Types/Repeater.html). + +### Drop-down Options + +Specify the options for the multi-select here. You can hardcode the values directly, or use a snippet to dynamically populate +the values. +See the section _Defining the Options_ on the [dropdown input page](https://docs.modmore.com/en/ContentBlocks/v1.x/Input_Types/Dropdown.html) for details, as it works the same way. + +### Output Separator + +Perhaps you would like to have the user select multiple resource ids to use in a [`getResources` snippet](https://docs.modx.com/3.x/en/extras/getresources). +You could add a comma here to separate each id. It doesn't have to be a comma though, it could be any character(s) you like. + +### Default Value + +A value, which exists in the multi-select options, that should be preselected when the field is added to a page. +The default value can have multiple values (if they exist) separated by commas. + +**Important:** If your default value is **empty**, the multi-select input will not select any values automatically. + +## Multi-Select Setting + +The multi-select input is also available as a setting (in a modal, as a field or as normal setting) for both layouts and +other fields. + +[ ![Multi-Select](../img/multi-select-setting.png)](../img/multi-select-setting.png) + +As you can see in the image above, the setting also has a template field, an output separator, field options and a default value field. +If you are going to use a snippet in the field options, be sure to check the process tags box. \ No newline at end of file diff --git a/en/02_ContentBlocks/v1.x/05_Input_Types/Repeater.md b/en/02_ContentBlocks/v1.x/05_Input_Types/Repeater.md index 869b1898..4e9f3e63 100755 --- a/en/02_ContentBlocks/v1.x/05_Input_Types/Repeater.md +++ b/en/02_ContentBlocks/v1.x/05_Input_Types/Repeater.md @@ -132,7 +132,7 @@ Now add the rest of the fields. This works the same, except we use different inp #### Biography - General Tab: - - Input Type: Rich Text (which will use [Redactor](https://www.modmore.com/extras/redactor/) or TinyMCE, depending which is installed) + - Input Type: Rich Text (which will use [Redactor](https://modmore.com/extras/redactor/) or TinyMCE, depending which is installed) - Key: bio (the placeholder will be `[[+bio]]`) - Width: 70% - Name: Biography diff --git a/en/02_ContentBlocks/v1.x/05_Input_Types/index.md b/en/02_ContentBlocks/v1.x/05_Input_Types/index.md index 0c55c9a1..447f8f60 100755 --- a/en/02_ContentBlocks/v1.x/05_Input_Types/index.md +++ b/en/02_ContentBlocks/v1.x/05_Input_Types/index.md @@ -2,7 +2,7 @@ title: Available Input Types --- -This page contains an **alphabetical** list of the _built-in_ input types for [ContentBlocks](https://www.modmore.com/contentblocks/). For information on building custom input types for things that are not included, check out the [Custom Inputs documentation](../Custom_Inputs/Developing_Custom_Inputs) and see the [List of Available Custom Input Types](../Custom_Inputs/Third_Party_Input_Types) for custom input types you can use. +This page contains an **alphabetical** list of the _built-in_ input types for [ContentBlocks](https://modmore.com/contentblocks/). For information on building custom input types for things that are not included, check out the [Custom Inputs documentation](../Custom_Inputs/Developing_Custom_Inputs) and see the [List of Available Custom Input Types](../Custom_Inputs/Third_Party_Input_Types) for custom input types you can use. [TOC] @@ -28,11 +28,25 @@ The chunk input type has no template. If your chunk relies on certain styling, y -[![](https://www.modmore.com/assets/uploads/7595c06a23a490d4b6e805f21c62d277.png)](https://www.modmore.com/assets/uploads/7595c06a23a490d4b6e805f21c62d277.png) +[![](https://modmore.com/assets/uploads/7595c06a23a490d4b6e805f21c62d277.png)](https://modmore.com/assets/uploads/7595c06a23a490d4b6e805f21c62d277.png) - + +## Chunk Selector + +The Chunk Selector input provides your editor a way to choose a chunk to display. This is in contrast to the _Chunk_ input, which displays a preselected chunk. + +After selecting a chunk, choose a related [property set](https://docs.modx.com/3.x/en/building-sites/properties-and-property-sets) to use, or specify a custom property. + +[![](../img/chunk-selector-input.png)](../img/chunk-selector-input.png) +## Checkbox + +Available in ContentBlocks 1.12 and above, this simple input type provides a checkbox that can be toggled to return +a boolean output. This is especially handy in repeaters, where there may be a desire to enable or disable individual rows. + +[![](../img/checkbox.png)](../img/checkbox.png) + ## Code @@ -53,27 +67,72 @@ Also see this tip for [Displaying (MODX) Code](../Tips_Tricks/Displaying_MODX_Co -[![](https://www.modmore.com/assets/uploads/e280ca4db15226f2778c7e119dc1600d.png)](https://www.modmore.com/assets/uploads/e280ca4db15226f2778c7e119dc1600d.png) +[![](https://modmore.com/assets/uploads/e280ca4db15226f2778c7e119dc1600d.png)](https://modmore.com/assets/uploads/e280ca4db15226f2778c7e119dc1600d.png) +## Color Picker + +The Color Picker input enables editors to pick any color they fancy from the pop-up color wheel, +or select from a group of curated color swatches. + +[![](../img/color-picker-window.png)](../img/color-picker-window.png) + +The Color Picker is available as a core input type, as well as all types of settings (as a modal, a field, or a straight-up setting). + +[![](../img/color-picker-setting.png)](../img/color-picker-setting.png) + +**Configuration** + +To set the default swatch colors, edit the comma-separated values in the `contentblocks.color_picker_defaults` system setting. +When using a color picker input type (as opposed to a setting), you can override these presets per field via the +field Properties tab. + +[![](../img/color-picker-defaults.png)](../img/color-picker-defaults.png) + + +## File + +The file input allows selecting or uploading files to be downloaded as attachments by your users. Select a file and then give it a title in the provided text field; this title will then display on the download link in the output. + +[![](../img/file-input.png)](../img/file-input.png) + +**Configuration** + +In the field properties, you can customize the template, maximum number of files allowed, media source and directory the files will be uploaded to, and the allowed file extensions. + +[![](../img/file-input-properties.png)](../img/file-input-properties.png) + +As you can see in the image above, there are two template fields that can be customized with your own markup. The following placeholders are available: + + - Template + - `[[+url]]` - The file URL + - `[[+title]]` - The file title specified by the user + - `[[+size]]` - The file size (note the optional `:cbFileFormatSize` output modifier!) + - Wrapper Template + - `[[+files]]` - A list of files with the markup specified by the above Template - ## Gallery While not quite as full featured as MoreGallery, the built-in Gallery input for ContentBlocks is quite nice. It allows you to limit the number of images editors can add and is fully template-able as you would expect. -The template property is used for each individual image (placeholders: `[[+idx]]`, `[[+url]]` and `[[+title]]`), while the wrapper template is used to wrap the images (placeholder: `[[+images]]`). +The template property is used for each individual image (placeholders: `[[+idx]]`, `[[+total]]`, `[[+url]]`, `[[+description]]` and `[[+title]]`), while the wrapper template is used to wrap the images (placeholder: `[[+images]]`). - +[![](https://modmore.com/assets/uploads/6b2273fa0b7ea82850c83f94a3e70ef8.png)](https://modmore.com/assets/uploads/6b2273fa0b7ea82850c83f94a3e70ef8.png) + +## MoreGallery Image Selector -[![](https://www.modmore.com/assets/uploads/6b2273fa0b7ea82850c83f94a3e70ef8.png)](https://www.modmore.com/assets/uploads/6b2273fa0b7ea82850c83f94a3e70ef8.png) +While not included in ContentBlocks by itself, if you have both MoreGallery (1.16+) and ContentBlocks installed, the MoreGallery Image Selector input is made available. - +> If you did not have ContentBlocks installed when installing MoreGallery 1.16+, you may need to reinstall MoreGallery before the ContentBlocks input type will be available. + +The Image Selector input enables you to select an image from any MoreGallery resource to include within your ContentBlocks layout. +[![](../img/image-selector-input.png)](../img/image-selector-input.png) +For more information, view the [MoreGallery Image Selector](https://docs.modmore.com/en/MoreGallery/v1.x/Image_Selector.html) documentation. ## Heading @@ -81,11 +140,10 @@ The heading input is a simple one, but extremely useful. It combines a drop down For example, a template could contain a link and and anchor to [automatically link headings](../Tips_Tricks/Auto_Linked_Headers), like we're doing on modmore.com. - -[![](https://www.modmore.com/assets/uploads/cf0526ac66123db933a73b506130c053.png)](https://www.modmore.com/assets/uploads/cf0526ac66123db933a73b506130c053.png) +[![](https://modmore.com/assets/uploads/cf0526ac66123db933a73b506130c053.png)](https://modmore.com/assets/uploads/cf0526ac66123db933a73b506130c053.png) @@ -117,9 +175,9 @@ The image is available through the `[[+url]]` placeholder in the template, and w -[![](https://www.modmore.com/assets/uploads/82308bae9d682e0df6aa26c8f29cf2e7.png)](https://www.modmore.com/assets/uploads/82308bae9d682e0df6aa26c8f29cf2e7.png) +[![](https://modmore.com/assets/uploads/82308bae9d682e0df6aa26c8f29cf2e7.png)](https://modmore.com/assets/uploads/82308bae9d682e0df6aa26c8f29cf2e7.png) -[![](https://www.modmore.com/assets/uploads/226117876a28868059b4da1b0e3a93b5.png)](https://www.modmore.com/assets/uploads/226117876a28868059b4da1b0e3a93b5.png) +[![](https://modmore.com/assets/uploads/226117876a28868059b4da1b0e3a93b5.png)](https://modmore.com/assets/uploads/226117876a28868059b4da1b0e3a93b5.png) @@ -133,7 +191,7 @@ Need to make complex lists? The List (and Ordered List) input type have you cove -[![](https://www.modmore.com/assets/uploads/0600fcde539a94c22b1864d5bbb69adb.png)](https://www.modmore.com/assets/uploads/0600fcde539a94c22b1864d5bbb69adb.png) +[![](https://modmore.com/assets/uploads/0600fcde539a94c22b1864d5bbb69adb.png)](https://modmore.com/assets/uploads/0600fcde539a94c22b1864d5bbb69adb.png) @@ -147,7 +205,7 @@ The Quote input type combines a simple textfield with a smaller input field to a -[![](https://www.modmore.com/assets/uploads/f30c46c28bb0725ed917ad29344a824b.png)](https://www.modmore.com/assets/uploads/f30c46c28bb0725ed917ad29344a824b.png) +[![](https://modmore.com/assets/uploads/f30c46c28bb0725ed917ad29344a824b.png)](https://modmore.com/assets/uploads/f30c46c28bb0725ed917ad29344a824b.png) @@ -155,13 +213,13 @@ The Quote input type combines a simple textfield with a smaller input field to a ## Rich Text -The rich text input uses the installed rich text editor, such as [Redactor](https://www.modmore.com/extras/redactor/) or TinyMCE, to provide the richtext editing experience your clients are already used to. If no supported rich text editor is installed, a simple textarea is shown instead. +The rich text input uses the installed rich text editor, such as [Redactor](https://modmore.com/extras/redactor/) or TinyMCE, to provide the richtext editing experience your clients are already used to. If no supported rich text editor is installed, a simple textarea is shown instead. -[![](https://www.modmore.com/assets/uploads/1cd44c5242245bf7754332f2ea6e8743.png)](https://www.modmore.com/assets/uploads/1cd44c5242245bf7754332f2ea6e8743.png) +[![](https://modmore.com/assets/uploads/1cd44c5242245bf7754332f2ea6e8743.png)](https://modmore.com/assets/uploads/1cd44c5242245bf7754332f2ea6e8743.png) @@ -179,7 +237,7 @@ It is possible to filter the available snippets based on name/IDs as well as cat -[![](https://www.modmore.com/assets/uploads/a9e5ae3f5f9b8770a1c28e9fd0455c27.png)](https://www.modmore.com/assets/uploads/a9e5ae3f5f9b8770a1c28e9fd0455c27.png) +[![](https://modmore.com/assets/uploads/a9e5ae3f5f9b8770a1c28e9fd0455c27.png)](https://modmore.com/assets/uploads/a9e5ae3f5f9b8770a1c28e9fd0455c27.png) @@ -193,7 +251,7 @@ Docs to be added. -[![](https://www.modmore.com/assets/uploads/76fde4cb13d90fb56d43c301f03af29a.png)](https://www.modmore.com/assets/uploads/76fde4cb13d90fb56d43c301f03af29a.png) +[![](https://modmore.com/assets/uploads/76fde4cb13d90fb56d43c301f03af29a.png)](https://modmore.com/assets/uploads/76fde4cb13d90fb56d43c301f03af29a.png) @@ -215,4 +273,4 @@ The Video input allows the user to either paste in a YouTube URL, or to search p -[![](https://www.modmore.com/assets/uploads/12ec4e5848bf5df6ddd62a916b977b6c.png)](https://www.modmore.com/assets/uploads/12ec4e5848bf5df6ddd62a916b977b6c.png) \ No newline at end of file +[![](https://modmore.com/assets/uploads/12ec4e5848bf5df6ddd62a916b977b6c.png)](https://modmore.com/assets/uploads/12ec4e5848bf5df6ddd62a916b977b6c.png) diff --git a/en/02_ContentBlocks/v1.x/06_Custom_Inputs/00_Developing_Custom_Inputs.md b/en/02_ContentBlocks/v1.x/06_Custom_Inputs/00_Developing_Custom_Inputs.md index cfcf9132..2924af35 100755 --- a/en/02_ContentBlocks/v1.x/06_Custom_Inputs/00_Developing_Custom_Inputs.md +++ b/en/02_ContentBlocks/v1.x/06_Custom_Inputs/00_Developing_Custom_Inputs.md @@ -199,6 +199,9 @@ ContentBlocks.openModal(title, html, options);
+ {% if (o.content_desc) { %} +

{%=o.content_desc%}

+ {% } %}
@@ -217,6 +220,14 @@ On top of the required markup, there are some useful classes/hooks you can use a - If you have a form in a modal, the styling is not automatically applied. You can either add a `.contentblocks-modal-field` class to a wrapping div in the modal, or add the `.contentblocks-input` class to the input itself. - To prevent a part of your input from being a drag target (for reordering fields in the content), simply add the `.prevent-drag` class to that part or a wrapper div. Be sure not to add that class to the outmost `.contentblocks-field` as then users wont be able of changing the position of your input type. +To show the content description, added in v1.12, you will need to add the following in the correct place. Typically this is inserted between the label and an input type, but you may chosoe a more appropriate location based on the type of input type. + +```html +{% if (o.content_desc) { %} +

{%=o.content_desc%}

+{% } %} +``` + If you're replicating (part of) what other inputs are doing, be sure to check out the source code of that input to see if there are any other specific classes/methods you can use to achieve the same effect. Chances are there is. All core inputs are located in assets/components/contentblocks/js/inputs/ - the unminified files are there as well - and templates in core/components/contentblocks/templates/inputs/. ## The Plugin diff --git a/en/02_ContentBlocks/v1.x/06_Custom_Inputs/02_Icons.md b/en/02_ContentBlocks/v1.x/06_Custom_Inputs/02_Icons.md index f9709d18..b5c1aed6 100755 --- a/en/02_ContentBlocks/v1.x/06_Custom_Inputs/02_Icons.md +++ b/en/02_ContentBlocks/v1.x/06_Custom_Inputs/02_Icons.md @@ -10,7 +10,7 @@ These icons were designed specifically for ContentBlocks by Jon Wallace Design. All icons will be shown in the Icons dropdown when adding a field or layout, but in case you want a separate look, here they are: -![](https://www.modmore.com/assets/uploads/2014/02/2014-02-25-13.57.04-Content_Blocks___MODX_Revolution.png)![](https://www.modmore.com/assets/uploads/2014/02/2014-02-25-13.57.31-Content_Blocks___MODX_Revolution.png)![](https://www.modmore.com/assets/uploads/2014/02/2014-02-25-13.57.49-Content_Blocks___MODX_Revolution.png) +![](https://modmore.com/assets/uploads/2014/02/2014-02-25-13.57.04-Content_Blocks___MODX_Revolution.png)![](https://modmore.com/assets/uploads/2014/02/2014-02-25-13.57.31-Content_Blocks___MODX_Revolution.png)![](https://modmore.com/assets/uploads/2014/02/2014-02-25-13.57.49-Content_Blocks___MODX_Revolution.png) All these icons are retina-ready too (not on this page), so should look great on your fancy screens as well. diff --git a/en/02_ContentBlocks/v1.x/06_Custom_Inputs/03_Third_Party_Input_Types.md b/en/02_ContentBlocks/v1.x/06_Custom_Inputs/03_Third_Party_Input_Types.md index ca9e6d21..0245a870 100755 --- a/en/02_ContentBlocks/v1.x/06_Custom_Inputs/03_Third_Party_Input_Types.md +++ b/en/02_ContentBlocks/v1.x/06_Custom_Inputs/03_Third_Party_Input_Types.md @@ -2,11 +2,11 @@ title: Available Third Party Input Types --- -Interested in using more than just the [built in input types](https://www.modmore.com/contentblocks/documentation/input-types/)? This page contains a list of the input types you can install that we know off. Know of any others? Let us know! +Interested in using more than just the [built in input types](https://modmore.com/contentblocks/documentation/input-types/)? This page contains a list of the input types you can install that we know off. Know of any others? Let us know! ## oEmbed Input -Developed by us here at modmore, the oEmbed Input can be installed via the [modmore.com package provider](https://www.modmore.com/about/package-provider/) as a free package. It was first released on April 26th 2014. +Developed by us here at modmore, the oEmbed Input can be installed via the [modmore.com package provider](https://modmore.com/about/package-provider/) as a free package. It was first released on April 26th 2014. The oEmbed Input Type allows you to embed content from a few dozen oEmbed-enabled content providers, by simply pasting in the link to the content. By making use of the [noembed.com](http://noembed.com/) web service, you have instant embed-ability for close to 50 content providers, varying from YouTube, Vimeo and Spotify, to Facebook, Twitter, Dropbox, Amazon and many more. diff --git a/en/02_ContentBlocks/v1.x/07_Import_Export.md b/en/02_ContentBlocks/v1.x/07_Import_Export.md index 9961a66d..92c03592 100755 --- a/en/02_ContentBlocks/v1.x/07_Import_Export.md +++ b/en/02_ContentBlocks/v1.x/07_Import_Export.md @@ -26,4 +26,10 @@ There are three import modes available, each with their own use cases and caveat If you need help figuring out the right import mode for your situation, please don't hesitate to get in touch with support@modmore.com. -[![](https://assets.modmore.com/uploads/2015/12/contentblocks_import.png)](https://assets.modmore.com/uploads/2015/12/contentblocks_import.png) \ No newline at end of file +[![](https://assets.modmore.com/uploads/2015/12/contentblocks_import.png)](https://assets.modmore.com/uploads/2015/12/contentblocks_import.png) + +## Handling Repeaters + +To import/export repeaters, make sure you're using at least v1.11 of ContentBlocks. Older versions could not properly import the subfields. + +While other fields in exports are backwards compatible, it's recommended to re-export any exports you commonly use on v1.11 to make sure it uses the new format. diff --git a/en/02_ContentBlocks/v1.x/08_Parsing_Templates.md b/en/02_ContentBlocks/v1.x/08_Parsing_Templates.md index 835b8dd3..9d928ab1 100755 --- a/en/02_ContentBlocks/v1.x/08_Parsing_Templates.md +++ b/en/02_ContentBlocks/v1.x/08_Parsing_Templates.md @@ -4,9 +4,11 @@ title: Parsing & Templates ContentBlocks provides a revolutionary way of managing content. With this new way of doing things, there are also a few things to keep in mind when developing websites - in particular related to the way your page will be parsed and what is and what isn't possible. This document will walk you through a few of these limitations and best practices. +[TOC] + ## When & Where -When you're using ContentBlocks, the layouts and fields you used are parsed **when the resource is saved**. This was done to make integration into your templates as easy as possible (by simply using `[[*content]]` in your template), as well as to prevent parsing the resource from slowing down the front-end of the website. As many [input types](Input_Types) offer very granular templateing, it is not uncommon for large or complex resources to take 0,5-2 seconds to fully parse, and you don't want that delay in front of your users. +When you're using ContentBlocks, the layouts and fields you used are parsed **when the resource is saved**. This was done to make integration into your templates as easy as possible (by simply using `[[*content]]` in your template), as well as to prevent parsing the resource from slowing down the front-end of the website. As many [input types](Input_Types) offer very granular templating, it is not uncommon for large or complex resources to take 0,5-2 seconds to fully parse, and you don't want that delay in front of your users. If you're changing field or layout templates, you will notice that this doesn't automatically update the resources using this content before the change. To parse every resource again, simply hit the "Rebuild Content" button in the component. This will kick off a process that loops over all of your resources and re-generates the content with the latest templates. diff --git a/en/02_ContentBlocks/v1.x/11_Internationalization.md b/en/02_ContentBlocks/v1.x/11_Internationalization.md index a7070c82..960ce15c 100755 --- a/en/02_ContentBlocks/v1.x/11_Internationalization.md +++ b/en/02_ContentBlocks/v1.x/11_Internationalization.md @@ -1,36 +1,50 @@ -ContentBlocks is available in English (default), German, French, Dutch, Polish, Russian and Swedish, [which we manage through CrowdIn](https://crowdin.net/project/modmore-contentblocks). This covers all core text, including instructions, buttons, labels, settings and more. +ContentBlocks itself is available in English (default), German, French, Dutch, Polish, Russian and Swedish, [which we manage through CrowdIn](https://crowdin.net/project/modmore-contentblocks). This covers all core text, including instructions, buttons, labels, settings and more. The data you define through the component (fields, layouts and templates) also supports translations since v1.1. This allows you to present different names and descriptions for your users depending on their manager language. We support lexicons on field, layout and template names and descriptions, as well as field and layout settings and properties on select input types (chunk, snippet and chunk selector). +At the moment ContentBlocks does not have a built-in way to translate your content. For this we recommend a multi-context solution (optionally with the Babel and/or LangRouter extras). Note that ContentBlocks and Lingua are **not** compatible. + +[TOC] + ## The Lexicon Files To load the lexicon, you will need to create a namespace and add a "lexicon" directory inside the namespace its core path. In there, you would have a directory for each language (`en`, `fr`, `de`, etc) and a file in each of those (e.g. `default.inc.php`). Within the file, you would add the lexicon entries to a `$_lang` variable. An example of a lexicon file is shown below. -```` PHP + +````PHP controller->addLexiconTopic('mynamespace:default'); ```` -Yeah, just that one line. Replace `mynamespace` with the name of your namespace, and `default` with the name of your lexicon topic (file). -To check if it's working, open up the source view for the resource update page, and look for the line that loads the lang.js.php with a whole bunch of topics separated by commas. It looks something like this: <`script src="/connectors/lang.js.php?ctx=mgr&topic=topmenu,file,resource...">` Your lexicon entry should be in that list. If it isn't, double check if you enabled the **OnDocFormRender** event, or try clearing the cache and refreshing. \ No newline at end of file +Just that one line. Replace `mynamespace` with the name of your namespace, and `default` with the name of your lexicon topic (file). + +To check if it's working, open up the source view for the resource update page, and look for the line that loads the lang.js.php with a whole bunch of topics separated by commas. It looks something like this: <`script src="/connectors/lang.js.php?ctx=mgr&topic=topmenu,file,resource...">` Your lexicon entry should be in that list. + +If it isn't, double check if you enabled the **OnDocFormRender** event, or try clearing the cache and refreshing. diff --git a/en/02_ContentBlocks/v1.x/12_Permissions.md b/en/02_ContentBlocks/v1.x/12_Permissions.md index 364e8717..b5116aa7 100755 --- a/en/02_ContentBlocks/v1.x/12_Permissions.md +++ b/en/02_ContentBlocks/v1.x/12_Permissions.md @@ -1,5 +1,9 @@ As of ContentBlocks 1.5, you have fine grained control over who can perform certain actions in the ContentBlocks Component. This uses the Access Control Lists features of MODX, that allows you to assign sets of permissions to a user group. +[TOC] + +## Introduction + During installation a Policy Template with the name `ContentBlocksTemplate` is created. This contains all the permissions for ContentBlocks, 35 at latest count, which you can add to Access Policies through that template. The full list can be seen in your manager, along with a brief description of each, by browsing to _System_ > _Access Control Lists_ > _Policy Templates_ > _ContentBlocksTemplate_. There are permissions that control access to the entire component (`contentblocks_component`) and it gets more granular from there on. With the `contentblocks_fields`, `contentblocks_layouts`, `contentblocks_templates`, `contentblocks_categories` and `contentblocks_defaults` permissions you can remove the specific tabs in one go. diff --git a/en/02_ContentBlocks/v1.x/13_Custom_Resources.md b/en/02_ContentBlocks/v1.x/13_Custom_Resources.md index ed894be8..cfcdbba1 100755 --- a/en/02_ContentBlocks/v1.x/13_Custom_Resources.md +++ b/en/02_ContentBlocks/v1.x/13_Custom_Resources.md @@ -4,14 +4,16 @@ title: Custom Resources As of ContentBlocks 1.1 it is possible to use it on a variety of custom resource types. -Once we have independently confirmed that third party custom resources work as expected with ContentBlocks, we will include it in the `contentblocks.accepted_resource_types` system setting so it is enabled by default. It is possible to manually add class keys to this setting if you want to test it with a resource type that we have not yet confirmed, or disable using ContentBlocks on certain resource types. +[TOC] ## Supported Custom Resource Types +Once we have independently confirmed that third party custom resources work as expected with ContentBlocks, we will include it in the `contentblocks.accepted_resource_types` system setting so it is enabled by default. It is possible to manually add class keys to this setting if you want to test it with a resource type that we have not yet confirmed, or disable using ContentBlocks on certain resource types. + The following Extras are known to work with ContentBlocks and enabled by default as of 1.1.0: - MoreGallery -- [SimpleCart](https://www.modmore.com/simplecart/) (as of v2.1.1) +- [SimpleCart](https://modmore.com/simplecart/) (as of v2.1.1) - [Articles](http://rtfm.modx.com/extras/revo/articles) (as of v1.7.7) - [GoodNews](http://www.bitego.com/extras/goodnews/) - [Collections](http://modx.com/extras/package/collections) diff --git a/en/02_ContentBlocks/v1.x/14_Events.md b/en/02_ContentBlocks/v1.x/14_Events.md new file mode 100644 index 00000000..34f16551 --- /dev/null +++ b/en/02_ContentBlocks/v1.x/14_Events.md @@ -0,0 +1,355 @@ +# ContentBlocks Events + +ContentBlocks provides several events that allow you to extend and customize its functionality. These events let you create custom input types, modify content before it's saved, and hook into the rendering process. + +## Quick Start + +Here are the most common scenarios: + +- **Create custom input types**: Use `ContentBlocks_RegisterInputs` to add your own field types +- **Modify content on save**: Use `ContentBlocks_RenderContent` to transform content before it's stored +- **Customize templates**: Use `ContentBlocks_BeforeParse` and `ContentBlocks_AfterParse` to modify how individual content is parsed + +## Available Events + +- `ContentBlocks_RegisterInputs` - Add custom input field types +- `ContentBlocks_RenderContent` - Modify content before saving +- `ContentBlocks_RebuildContent` - Hook into content rebuild process +- `ContentBlocks_AfterRebuildContent` - Run code after rebuild completes +- `ContentBlocks_BeforeParse` - Modify templates before rendering +- `ContentBlocks_AfterParse` - Modify final output after rendering + +[TOC] + +## ContentBlocks_RegisterInputs + +**Purpose**: Create custom input field types for ContentBlocks + +**When it fires**: When ContentBlocks loads its input types (during page load) + +**What you get**: +- `contentBlocks` - The ContentBlocks service object + +**What to return**: An array mapping your input name to a custom input class + +### Creating a Custom Input + +To create a custom input type, you need to: + +1. Create a class that extends `cbBaseInput` +2. Return it in an array from your plugin + +**Example**: Creating a custom "Color Picker" input. Typically you'd put the class itself in a file of its own. + +```php +// System Event: ContentBlocks_RegisterInputs +$cb = $scriptProperties['contentBlocks']; + +class ColorPickerInput extends cbBaseInput { + public function getFieldProperties() { + return [ + 'color' => [ + 'xtype' => 'colorfield', + 'fieldLabel' => 'Color', + 'value' => '#000000' + ] + ]; + } + + public function process($value, $field) { + return '
' . $value . '
'; + } +} + +return [ + 'colorpicker' => new ColorPickerInput($cb) +]; +``` + +**Important Notes**: +- Always return an array, never echo or print anything +- Your class must extend `cbBaseInput` +- ContentBlocks will automatically load any lexicon topics you define + +## ContentBlocks_RenderContent + +**Purpose**: Modify content before it's saved to the database + +**When it fires**: +- When a resource is saved (after content is retrieved but before HTML is generated) +- During content rebuild operations + +**What you get**: +- `cbContent` - The ContentBlocks content as an array +- `cbJson` - The original JSON string from the database +- `resource` - The MODX resource object + +**What to return**: An array with modified content, or nothing if no changes are needed + +### Common Use Cases + +- **Data Migration**: Update field names or structure when upgrading +- **Content Validation**: Ensure content meets business rules +- **Content Enhancement**: Add metadata or transform values + +**Example**: Adding a timestamp to all text blocks + +```php +// System Event: ContentBlocks_RenderContent +$cbContent = $scriptProperties['cbContent']; +$cbJson = $scriptProperties['cbJson']; +$resource = $scriptProperties['resource']; + +$modified = false; + +// Add timestamp to all text blocks +foreach ($cbContent as &$block) { + if ($block['field'] === 'text' && !empty($block['value'])) { + $block['value'] .= "\n

Last updated: " . date('Y-m-d H:i:s') . "

"; + $modified = true; + } +} + +if ($modified) { + // Update the JSON string + $cbJson = $modx->toJSON($cbContent); + return [ + 'cbContent' => $cbContent, + 'cbJson' => $cbJson + ]; +} + +// No changes needed +return null; +``` + +**Important Notes**: +- Multiple plugins can run - only the first non-empty response is used +- Return `null` or nothing if you don't want to modify the content +- Always update both `cbContent` and `cbJson` when making changes + +## ContentBlocks_RebuildContent + +**Purpose**: Run code during the content rebuild process + +**When it fires**: During "Rebuild Content" operations, for each resource being rebuilt + +**What you get**: +- `cbContent` - The ContentBlocks content array +- `resource` - The MODX resource object being rebuilt + +**What to return**: Nothing (return value is ignored) + +### Common Use Cases + +- **Progress Tracking**: Log which resources are being processed +- **Cache Management**: Clear caches for specific resources +- **External Integration**: Update search indexes or external systems + +**Example**: Logging rebuild progress + +```php +// System Event: ContentBlocks_RebuildContent +$resource = $scriptProperties['resource']; +$cbContent = $scriptProperties['cbContent']; + +// Log the rebuild progress +$modx->log(modX::LOG_LEVEL_INFO, + '[ContentBlocks] Rebuilding resource #' . $resource->get('id') . + ' (' . $resource->get('pagetitle') . ')' +); + +// Optional: Clear any cached data for this resource +if ($modx->getCacheManager()) { + $modx->cacheManager->delete('resource/' . $resource->get('id')); +} +``` + +## ContentBlocks_AfterRebuildContent + +**Purpose**: Run code after the entire rebuild process completes + +**When it fires**: After all resources have been processed during a rebuild operation + +**What you get**: +- `total` - Total number of resources processed +- `total_skipped` - Number of resources skipped (not using ContentBlocks) +- `total_skipped_broken` - Number skipped due to corrupted data +- `total_rebuild` - Number of resources successfully rebuilt + +**What to return**: Nothing (return value is ignored) + +### Common Use Cases + +- **Cache Management**: Clear or warm up caches after rebuild +- **External Systems**: Update search indexes or trigger external processes + +**Example**: Sending a completion notification + +```php +// System Event: ContentBlocks_AfterRebuildContent +$total = $scriptProperties['total']; +$rebuilt = $scriptProperties['total_rebuild']; +$skipped = $scriptProperties['total_skipped']; +$broken = $scriptProperties['total_skipped_broken']; + +// Log completion statistics +$modx->log(modX::LOG_LEVEL_INFO, + '[ContentBlocks] Rebuild completed: ' . $rebuilt . ' rebuilt, ' . + $skipped . ' skipped, ' . $broken . ' broken' +); + +// Optional: Send notification email +if ($rebuilt > 0) { + $message = "ContentBlocks rebuild completed successfully.\n"; + $message .= "Resources rebuilt: " . $rebuilt . "\n"; + $message .= "Resources skipped: " . $skipped . "\n"; + $message .= "Resources with errors: " . $broken; + + // Send email notification (implement your email logic here) + // mail('admin@yoursite.com', 'ContentBlocks Rebuild Complete', $message); +} +``` + +## ContentBlocks_BeforeParse + +> **Note**: This event was added in ContentBlocks 1.15.0-pl + +**Purpose**: Modify templates before they're processed and rendered + +**When it fires**: Before ContentBlocks processes a template (before placeholder replacement) + +**What you get**: +- `tpl` - The template string (HTML, @CHUNK, @FILE, etc.) +- `phs` - Array of placeholders that will be used + +**What to return**: A new template string, or nothing if no changes needed + +### Common Use Cases + +- **Dynamic Templates**: Switch templates based on conditions +- **Template Injection**: Add wrapper markup or modify structure +- **Conditional Rendering**: Use different chunks based on content + +**Example**: Implementing a custom Twig parser + +```php +// System Event: ContentBlocks_BeforeParse +$tpl = $scriptProperties['tpl']; +$phs = $scriptProperties['phs']; + +// Check if this template uses Twig syntax +if (strpos($tpl, '{{') !== false || strpos($tpl, '{%') !== false) { + // Load Twig if not already loaded + if (!class_exists('Twig\Environment')) { + require_once MODX_CORE_PATH . 'components/twig/vendor/autoload.php'; + } + + try { + // Create Twig environment + $loader = new \Twig\Loader\ArrayLoader(['template' => $tpl]); + $twig = new \Twig\Environment($loader); + + // Add custom filters and functions + $twig->addFilter(new \Twig\TwigFilter('modx_resource', function($id) use ($modx) { + $resource = $modx->getObject('modResource', $id); + return $resource ? $resource->toArray() : null; + })); + + $twig->addFunction(new \Twig\TwigFunction('modx_chunk', function($name) use ($modx) { + $chunk = $modx->getObject('modChunk', ['name' => $name]); + return $chunk ? $chunk->getContent() : ''; + })); + + // Render the template with ContentBlocks placeholders + $rendered = $twig->render('template', $phs); + + // Return the rendered template + $modx->event->output($rendered); + + } catch (Exception $e) { + // Log error and fall back to original template + $modx->log(modX::LOG_LEVEL_ERROR, + '[ContentBlocks] Twig parsing error: ' . $e->getMessage() + ); + } +} + +// No changes needed +return null; +``` + +**Important Notes**: +- You can't modify placeholders directly - only the template +- Multiple plugins can run - only the first non-empty response is used +- Keep processing fast as this runs for every block during rendering + +## ContentBlocks_AfterParse + +> **Note**: This event was added in ContentBlocks 1.15.0-pl + +**Purpose**: Modify the final HTML output after all processing is complete + +**When it fires**: After ContentBlocks has finished processing and rendering the template + +**What you get**: +- `tpl` - The final HTML output string +- `phs` - The placeholders that were used during processing + +**What to return**: A modified HTML string, or nothing if no changes needed + +### Common Use Cases + +- **Output Enhancement**: Add CSS classes, wrap content, or inject scripts +- **Content Processing**: Minify HTML, add analytics tracking, or modify URLs +- **Security**: Sanitize output or add security headers + +**Example**: Adding responsive wrapper and analytics tracking + +```php +// System Event: ContentBlocks_AfterParse +$output = $scriptProperties['tpl']; +$phs = $scriptProperties['phs']; + +// Add responsive wrapper if specified +if (!empty($phs['responsive']) && $phs['responsive'] === 'true') { + $output = '
' . $output . '
'; +} + +// Add analytics tracking for specific content types +if (!empty($phs['content_type']) && $phs['content_type'] === 'hero') { + $output .= ''; +} + +// Add lazy loading to images +$output = preg_replace('/]+)src=/', 'event->output($output); +``` + +**Important Notes**: +- This runs for every block during rendering - keep it fast +- Multiple plugins can run - only the first non-empty response is used +- This is your last chance to modify the output before it's saved + +## Best Practices + +### Performance Considerations + +- **Keep it fast**: `BeforeParse` and `AfterParse` run for every content block during rendering +- **Avoid heavy operations**: Don't make database queries or external API calls in these events +- **Cache when possible**: Store expensive calculations and reuse them + +### Multiple Plugins + +When multiple plugins respond to the same event: +- Only the first non-empty response is used +- Return `null` or nothing if you don't want to modify anything +- This prevents conflicts between different plugins + +### Error Handling + +- Always validate your data before processing +- Use try-catch blocks for risky operations +- Log errors appropriately for debugging diff --git a/en/02_ContentBlocks/v1.x/Tips_Tricks/02_Load_Field_Specific_Assets.md b/en/02_ContentBlocks/v1.x/Tips_Tricks/02_Load_Field_Specific_Assets.md index 4e03872c..634a746b 100755 --- a/en/02_ContentBlocks/v1.x/Tips_Tricks/02_Load_Field_Specific_Assets.md +++ b/en/02_ContentBlocks/v1.x/Tips_Tricks/02_Load_Field_Specific_Assets.md @@ -4,7 +4,7 @@ This Tip makes use of the cbHasField snippet, included in the ContentBlocks core ## The Setup -In this case, we're using the [Displaying (MODX) Code tip](https://www.modmore.com/contentblocks/tips-tricks/displaying-code/) as example. We want to only load our syntax highlight script, in this case Prism, when we have a code input in the content. +In this case, we're using the [Displaying (MODX) Code tip](https://modmore.com/contentblocks/tips-tricks/displaying-code/) as example. We want to only load our syntax highlight script, in this case Prism, when we have a code input in the content. Prism consists of [two files](http://prismjs.com/download.html) you'll need on your server, a CSS file (which should go into the ``) and a javascript file (which should go right before the ``). Let's assume that you have uploaded these files to /assets/js/prism.css and /assets/style/prism.js, and that the code field you created earlier has an ID of 4. diff --git a/en/02_ContentBlocks/v1.x/img/checkbox.png b/en/02_ContentBlocks/v1.x/img/checkbox.png new file mode 100644 index 00000000..5643ae97 Binary files /dev/null and b/en/02_ContentBlocks/v1.x/img/checkbox.png differ diff --git a/en/02_ContentBlocks/v1.x/img/chunk-selector-input.png b/en/02_ContentBlocks/v1.x/img/chunk-selector-input.png new file mode 100644 index 00000000..b360b469 Binary files /dev/null and b/en/02_ContentBlocks/v1.x/img/chunk-selector-input.png differ diff --git a/en/02_ContentBlocks/v1.x/img/color-picker-defaults.png b/en/02_ContentBlocks/v1.x/img/color-picker-defaults.png new file mode 100644 index 00000000..4f260863 Binary files /dev/null and b/en/02_ContentBlocks/v1.x/img/color-picker-defaults.png differ diff --git a/en/02_ContentBlocks/v1.x/img/color-picker-setting.png b/en/02_ContentBlocks/v1.x/img/color-picker-setting.png new file mode 100644 index 00000000..ccca1316 Binary files /dev/null and b/en/02_ContentBlocks/v1.x/img/color-picker-setting.png differ diff --git a/en/02_ContentBlocks/v1.x/img/color-picker-window.png b/en/02_ContentBlocks/v1.x/img/color-picker-window.png new file mode 100644 index 00000000..d7c63d2a Binary files /dev/null and b/en/02_ContentBlocks/v1.x/img/color-picker-window.png differ diff --git a/en/02_ContentBlocks/v1.x/img/crops-preview.gif b/en/02_ContentBlocks/v1.x/img/crops-preview.gif new file mode 100644 index 00000000..b9c49152 Binary files /dev/null and b/en/02_ContentBlocks/v1.x/img/crops-preview.gif differ diff --git a/en/02_ContentBlocks/v1.x/img/file-input-properties.png b/en/02_ContentBlocks/v1.x/img/file-input-properties.png new file mode 100644 index 00000000..915868ec Binary files /dev/null and b/en/02_ContentBlocks/v1.x/img/file-input-properties.png differ diff --git a/en/02_ContentBlocks/v1.x/img/file-input.png b/en/02_ContentBlocks/v1.x/img/file-input.png new file mode 100644 index 00000000..0fc34764 Binary files /dev/null and b/en/02_ContentBlocks/v1.x/img/file-input.png differ diff --git a/en/02_ContentBlocks/v1.x/img/image-cropper.jpg b/en/02_ContentBlocks/v1.x/img/image-cropper.jpg new file mode 100644 index 00000000..35a95d2e Binary files /dev/null and b/en/02_ContentBlocks/v1.x/img/image-cropper.jpg differ diff --git a/en/02_ContentBlocks/v1.x/img/image-selector-input.png b/en/02_ContentBlocks/v1.x/img/image-selector-input.png new file mode 100644 index 00000000..f1228dd7 Binary files /dev/null and b/en/02_ContentBlocks/v1.x/img/image-selector-input.png differ diff --git a/en/02_ContentBlocks/v1.x/img/multi-select-field-properties.png b/en/02_ContentBlocks/v1.x/img/multi-select-field-properties.png new file mode 100644 index 00000000..8364e673 Binary files /dev/null and b/en/02_ContentBlocks/v1.x/img/multi-select-field-properties.png differ diff --git a/en/02_ContentBlocks/v1.x/img/multi-select-input-type.png b/en/02_ContentBlocks/v1.x/img/multi-select-input-type.png new file mode 100644 index 00000000..1fb804ec Binary files /dev/null and b/en/02_ContentBlocks/v1.x/img/multi-select-input-type.png differ diff --git a/en/02_ContentBlocks/v1.x/img/multi-select-setting.png b/en/02_ContentBlocks/v1.x/img/multi-select-setting.png new file mode 100644 index 00000000..c973445f Binary files /dev/null and b/en/02_ContentBlocks/v1.x/img/multi-select-setting.png differ diff --git a/en/02_ContentBlocks/v1.x/img/template-property.jpg b/en/02_ContentBlocks/v1.x/img/template-property.jpg new file mode 100644 index 00000000..f00f6161 Binary files /dev/null and b/en/02_ContentBlocks/v1.x/img/template-property.jpg differ diff --git a/en/02_ContentBlocks/v1.x/index.md b/en/02_ContentBlocks/v1.x/index.md index daeb7ead..1b469a8c 100644 --- a/en/02_ContentBlocks/v1.x/index.md +++ b/en/02_ContentBlocks/v1.x/index.md @@ -1,9 +1,9 @@ --- -title: ContentBlocks -description: Documentation for ContentBlocks, a premium extra from modmore for MODX. +title: ContentBlocks 1.x +description: Documentation for ContentBlocks, a premium extra from modmore for MODX. --- -[ContentBlocks](https://www.modmore.com/contentblocks/) is a powerful content manager for MODX allowing editors to create modular, multi-column content. +[ContentBlocks](https://modmore.com/contentblocks/) is a powerful content manager for MODX allowing editors to create modular, multi-column content. # Recommended Reading diff --git a/en/02_DigitalSignage/images/create-slide.jpg b/en/02_DigitalSignage/images/create-slide.jpg new file mode 100644 index 00000000..1b360d68 Binary files /dev/null and b/en/02_DigitalSignage/images/create-slide.jpg differ diff --git a/en/02_DigitalSignage/v1/01_Getting_Started.md b/en/02_DigitalSignage/v1/01_Getting_Started.md new file mode 100644 index 00000000..0914da49 --- /dev/null +++ b/en/02_DigitalSignage/v1/01_Getting_Started.md @@ -0,0 +1,59 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +To get started with Digital Signage, you need a license. We offer [free development licenses](https://modmore.com/free-development-licenses/) that you can use to try out Digital Signage, and also for development and staging purposes. [Paid licenses can be found here](https://modmore.com/digitalsignage/pricing/). + +[TOC] + +## Installing the package + +After creating an [api key](https://modmore.com/account/api-keys/) and adding it to your MODX site, you can browse our package provider to download Digital Signage. If you're new to modmore, [learn more about how our package provider works here](https://modmore.com/about/package-provider/). + +When you install the package, a few things will be created for you: + +- A new Context, called "Digital Signage" (`ds`) which is set to have a base url of `/ds`, meaning your digital signage will be available at `http://yourmodxsite.com/ds/`. + +- A new template, called `Digital Signage (1.1.4-pl original)`, or with a different version number. + +- Several resources in the `ds` context including a home and export resources. You wont have to edit these manually usually. + +- A link in the top menu called Digital Signage. This points to the dashboard, which is where you'll manage your slideshows. + +- There are also [permissions](Permissions) that are added on installation; the administrator user group is automatically given these during the installation. + +A couple of [settings](Configuration) are also set automatically based on what was created. This includes the context, templates adn more. The standard configuration should be good to start with. + +## Creating a template + +Before moving on, duplicate the default template that was created and give it a name of your own. **Without a custom template, your broadcast wont work!** + +Edit the `digitalsignage.templates` system setting and add your own template ID separated with a comma, for example `5,6`. **You need to have at least 2 options in the setting!** + +## Creating your first broadcast + +Click on the Digital Signage button in the MODX menu to go to the management dashboard. You'll notice a few tabs: + +- **Broadcasts** are your slideshows. They are assigned to players (third tab) and contain slides (second tab). +- **Slides** (second tab) are the individual pages inside your slideshow. There are different [types of slides](Slide_Types) you can use, as well as custom ones. Depending on the slide type, you can manage the content through this tab. +- **Players** is where you define the different screens you will be showing your broadcasts on. Each screen or device you want to play a broadcast should be a unique player. For each player you can set a schedule. + +First, let's create a few slides. + +On the Slides tab, click on **Create new slide**. In the window that opens, select **Default** as the type, check _Published_ and enter a title, content, and how long the slide should be shown. You can also add an image and choose if you want to show the ticker or not. + +Create another slide with type **Buienradar**, which can show the weather. Find a location ID per the shown instructions or use `2751792` for Leeuwarden as an example. Give it a title as well. + +![Creating a slide](../images/create-slide.jpg) + +When you have slides, move to the **Broadcasts** tab and click **Create new broadcast**. Enter a name, select a template, and save. Right click and choose **Update slides (internal slides)**. Drag and drop the slides you created from the right _Available Slides_ to the left _Selected Slides_ column. Close the modal. + +> **If you do not have the option to select a template, make sure to duplicate the default template and add at least 2 options to the `digitalsignage.templates` system setting.** Failing to do so can cause your broadcasts to be created without a template due to an unresolved bug, meaning you only get a blank page when viewing it. + +## Connecting a screen (player) + +Before we can view the broadcast, we need to connect a screen. On the **Players** tab, create a new player, giving it a nice name and enter a resolution (e.g. `1920x1080`). You can change this later if you don't have a dedicated screen yet. + +Save, and then right click the player in the list and choose **Schedule Player**. Add a schedule entry **Connect Player**. You'll see a link; that's the one you need to open on your player. + +When you open the link on the screen, you can now start managing it from the Digital Signage dashboard. When you change a broadcast or schedule, it will automatically load on your screen within 5 minutes. diff --git a/en/02_DigitalSignage/v1/Configuration.md b/en/02_DigitalSignage/v1/Configuration.md new file mode 100644 index 00000000..1fad18b4 --- /dev/null +++ b/en/02_DigitalSignage/v1/Configuration.md @@ -0,0 +1,18 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +When installing DigitalSignage, most configuration is automatically set up for you. For advanced uses, there are a few things you can tweak. + +[TOC] + +## System Settings + +- `digitalsignage.context` The key of the Digital Signage context. +- `digitalsignage.export_resource` The ID of Home resource within the Digital Signage context. +- `digitalsignage.request_resource` The ID of Export resource within the Digital Signage context. +- `digitalsignage.templates` Comma delimited list of Digital Signage templates. +- `digitalsignage.auto_create_sync` Automatically synchronize when no data is available. +- `digitalsignage.media_source` The media source that is used for media files. +- `digitalsignage.request_param_broadcast` GET-parameter to identify the broadcast. +- `digitalsignage.request_param_player` GET-parameter to identify the player. diff --git a/en/02_DigitalSignage/v1/Custom_Templates.md b/en/02_DigitalSignage/v1/Custom_Templates.md new file mode 100644 index 00000000..69a5fd9b --- /dev/null +++ b/en/02_DigitalSignage/v1/Custom_Templates.md @@ -0,0 +1,22 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +Upon installation you'll find a new template called `DigitalSignage (1.x.x original)`. As the name implies, this is a default template that **will be overwritten on upgrades**, so you'll want to avoid editing it directly. + +[TOC] + +## Setting a custom template + +To start tweaking your design, first duplicate the original template. + +Go to System > System Settings and change the `digitalsignage.templates` system setting to include the ID of the new template you just created. This setting accepts a comma separated list of template IDs, so if its value is for example `2` and your template is ID `3`, you can set it to `2,3`. + +In the Digital Signage dashboard, on the Broadcasts tab, right click the broadcast you want to use with your own template and choose _Update broadcast_. Choose your template under Templates, and save. + +## Editing the template + +Now that your broadcast uses a new template, you can start changing things. Let's take a look; open your duplicated template. You'll find it's built with HTML, CSS and JS, so you can change it quite a bit! + +First off, you'll probably want to add a custom CSS file to hold your tweaks. It's useful to keep the original CSS in place, as that contains all the needed styles for the basic layout and core plugins (ticker and clock). Keeping your tweaks separated will help with maintenance and upgrading Digital Signage in the future. + diff --git a/en/02_DigitalSignage/v1/Permissions.md b/en/02_DigitalSignage/v1/Permissions.md new file mode 100644 index 00000000..cd17aaf0 --- /dev/null +++ b/en/02_DigitalSignage/v1/Permissions.md @@ -0,0 +1,11 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +Digital Signage offers the following permissions that you can use with the MODX ACL system to manage access to the dashboard. + +- `digitalsignage` With this policy you can manage slides, broadcasts and media players. +- `digitalsignage_settings` With this policy you can manage slides, broadcasts, media players and slide types. + +If you'd like to restrict access to the digital signage component, create a Policy Template with those permissions, +a Policy based on that template, and add the policy as mgr context permission to a usergroup. diff --git a/en/02_DigitalSignage/v1/RSS_Feeds.md b/en/02_DigitalSignage/v1/RSS_Feeds.md new file mode 100644 index 00000000..7bffd460 --- /dev/null +++ b/en/02_DigitalSignage/v1/RSS_Feeds.md @@ -0,0 +1,21 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +There are 2 ways of integrating RSS feeds. On a specific slide, as an automatic external feed, or as a news ticker. + +[TOC] + +## On a specific slide + +Create a new slide of type "RSS Feed" and enter the feed URL. Add the slide to a broadcast. + +## As an automatic integrated feed + +Right click a broadcast and choose "Update feeds (external slides)" and choose "Create new feed". + +Enter the RSS feed URL and choose how often to show it by setting the Frequency. If you set the frequency to 2, it means an item from the feed will be automatically added after every 2 regular slides. + +## As a news ticker + +The news ticker scrolls past the bottom of the screen on each slide. To set it, right click your broadcast and choose _Update Broadcast_. Enter the URL of a RSS feed in the Ticker URL feed. diff --git a/en/02_DigitalSignage/v1/Slide_Types/Adding_Custom_Types.md b/en/02_DigitalSignage/v1/Slide_Types/Adding_Custom_Types.md new file mode 100644 index 00000000..ce3b255d --- /dev/null +++ b/en/02_DigitalSignage/v1/Slide_Types/Adding_Custom_Types.md @@ -0,0 +1,7 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +It's possible to create your custom slide types as well. This requires changing your [template](../Custom_Templates) and adding the slide type in the Digital Signage dashboard. + +Instructions on how to do that will follow here, soon. diff --git a/en/02_DigitalSignage/v1/Slide_Types/Social_Media.md b/en/02_DigitalSignage/v1/Slide_Types/Social_Media.md new file mode 100644 index 00000000..1e56c17c --- /dev/null +++ b/en/02_DigitalSignage/v1/Slide_Types/Social_Media.md @@ -0,0 +1,63 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +To integrate recent Facebook, Twitter & Instagram posts, you can use the free [Social Media extension for Digital Signage](https://modmore.com/digitalsignage/extensions/social-media/). + +## Setting up your template + +First, you need to have a [custom template](../Custom_Templates). We'll make changes to it to support the Social Media plugin, and don't want those reverted when you next update Digital Signage. + +#### Adding CSS Styles + +In the header, after the main.css file from Digital Signage, add the following CSS: + +````html + +```` + +#### Adding Slide HTML + +Somewhere in the middle (around line 55 in the default template) you should find a `
`. Add the following inside that div to act as a template for our Social Media slides.. + +````html + + + +```` + +#### Adding JavaScript Plugin + +Next, way in the footer, but before digitalsignage.js is included, load the Social Media plugin JavaScript: + +````html + +```` + +## Adding new Slide Type + +In the Digital Signage dashboard, click on Admin View in the top right and add a new Slide Type with key `social_media`, a name and icon of your choosing (e.g. `icon-heart`). + +## Adding a new Slide + +Go back to the default view with the button in the top right, and add a new slide using the slide type you just created. + +## Adding Social Media access tokens + +In System > System Settings open the `digitalsignagesocialmedia` namespace to find the various access credentials you'll need, as well as search options. You only have to add the tokens for the social media you want to integrate with. + +To check if the credentials are working, you can view the "Export (social media)" resource in your digitalsignage context. That should contain your post, or might contain error messages. diff --git a/en/02_DigitalSignage/v1/Slide_Types/index.md b/en/02_DigitalSignage/v1/Slide_Types/index.md new file mode 100644 index 00000000..541a4584 --- /dev/null +++ b/en/02_DigitalSignage/v1/Slide_Types/index.md @@ -0,0 +1,12 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +Digital Signage ships with the following slide types out of the box: + +- **Default** which consists of rich text (support Redactor, TinyMCE and other RTEs) and an optional image. +- **Media** which is either an image or a YouTube/Vimeo video. Best played full screen. +- **RSS Feed** to show a list of items from a RSS feed. ([learn more about different ways of integrating feeds](../RSS_Feeds)) +- **Buienradar** integrates the weather forecast, using an API from Buienradar. While Buienradar is a Dutch site, their forecast does have worldwide coverage. + +![Creating a slide](../../images/create-slide.jpg) diff --git a/en/02_DigitalSignage/v1/index.md b/en/02_DigitalSignage/v1/index.md new file mode 100644 index 00000000..65b8a39e --- /dev/null +++ b/en/02_DigitalSignage/v1/index.md @@ -0,0 +1,17 @@ +--- +title: DigitalSignage +description: Documentation for Digital Signage, a plugin by Sterc that lets you manage slideshows for narrow casting. +--- + +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + + +[DigitalSignage](https://modmore.com/digitalsignage/) is a premium extra by Sterc that lets you manage slideshows for narrow casting. [Learn more about DigitalSignage](https://modmore.com/digitalsignage/) + +Recommended reading: + +- [Getting Started](Getting_Started) +- [Custom templates](Custom_Templates) +- [Slide types](Slide_Types) diff --git a/en/03_Formalicious/images/createfieldchunkv2.png b/en/03_Formalicious/images/createfieldchunkv2.png new file mode 100644 index 00000000..152b3209 Binary files /dev/null and b/en/03_Formalicious/images/createfieldchunkv2.png differ diff --git a/en/03_Formalicious/v1/01_Installation.md b/en/03_Formalicious/v1/01_Installation.md index 6c63caf5..01b6484f 100755 --- a/en/03_Formalicious/v1/01_Installation.md +++ b/en/03_Formalicious/v1/01_Installation.md @@ -1,3 +1,7 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + Installing Formalicious requires the free Extra _FormIt 2.2.11-pl_ to function properly. FormIt is also maintained by us and thus, should guarantee maximum compatibility between FormIt and Formalicious. The MODX installer should install this automatically when installing Formalicious from the modmore repository. A custom manager page called _Formalicious_ is installed within the _Extras_ menu. Also a Template Variable and Element Category named _Formalicious_ are created. The _Template Variable_ should be assigned to all the templates you wish to use Formalicious forms on and a Snippet should be added to those templates. @@ -8,12 +12,12 @@ To accomplish this, follow these steps: 3. Enable the checkmarks for the templates on which you want to use Formalicious-forms 4. Save your changes 5. Go to every template you just enabled -6. In the field _Template code (HTML)_, add the following Snippet-call at the location where you want to show your forms: ```[[!renderForm? &form=`[[!*formalicious]]`]]``` We recommend to add it just below the ```[[*content]]``` placeholder, because it enables your content-managers to add text above the form. +6. In the field _Template code (HTML)_, add the following Snippet-call at the location where you want to show your forms: ```[[!renderForm? &form=`[[!*formalicious]]`]]``` We recommend to add it just below the ```[[*content]]``` placeholder, because it enables your content-managers to add text above the form. 7. An alternative would be to create a chunk called _form_ where you add the above Snippet-call. Instruct your content-managers to add the chunk-code ```[[$form]]``` anywhere they want, so they have more flexibility regarding the location of their forms, e.g. in-between two paragraphs. 8. Save your changes ## Inserting a form with ContentBlocks -If you also use [ContentBlocks](https://www.modmore.com/contentblocks/), you can use a field to select a form to insert as well, instead of needing the template variable and form code in your template. This gives your content editors more control over what form is inserted at what position. +If you also use [ContentBlocks](https://modmore.com/contentblocks/), you can use a field to select a form to insert as well, instead of needing the template variable and form code in your template. This gives your content editors more control over what form is inserted at what position. -Formalicious will add its custom input type during installation. At Extras > ContentBlocks, create a new field using the "Formalicious Form Selector" input type and customise the template as needed. +Formalicious will add its custom input type during installation. At Extras > ContentBlocks, create a new field using the "Formalicious Form Selector" input type and customise the template as needed. diff --git a/en/03_Formalicious/v1/02_Media_Sources.md b/en/03_Formalicious/v1/02_Media_Sources.md index 33acb82a..45e7563b 100755 --- a/en/03_Formalicious/v1/02_Media_Sources.md +++ b/en/03_Formalicious/v1/02_Media_Sources.md @@ -1,5 +1,9 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + Formalicious contains one _System Setting_: `formalicious.source`, which defaults to `1`. This is the default _Filesystem_ media source. Set this to the media source ID you wish to use when selecting email-attachments for auto-replies. -You can find an overview of all your media sources by clicking _Media Sources_ in the _Media_ menu. The first column in the media sources table can be used as the ID of the `formalicious.source` setting. \ No newline at end of file +You can find an overview of all your media sources by clicking _Media Sources_ in the _Media_ menu. The first column in the media sources table can be used as the ID of the `formalicious.source` setting. diff --git a/en/03_Formalicious/v1/03_Categories.md b/en/03_Formalicious/v1/03_Categories.md index cc14e167..a1875908 100755 --- a/en/03_Formalicious/v1/03_Categories.md +++ b/en/03_Formalicious/v1/03_Categories.md @@ -1,7 +1,11 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + Organising your forms from the start is highly recommended. You can do this by creating Form Categories. Categories allow you to group forms into tabs. Create tabs by going to the Formalicious page in the Extras-menu and click on _Admin panel_. Manage your _Categories_ in the first tab. The category-name will be displayed as the tab-name, followed by the description, which can be used to explain to your users what the category is used for. -**Please be aware:** forms can go missing when removing their parent category. Always make sure a category is empty before removing it. Version 1.1.0 will change this behaviour. \ No newline at end of file +**Please be aware:** forms can go missing when removing their parent category. Always make sure a category is empty before removing it. Version 1.1.0 will change this behaviour. diff --git a/en/03_Formalicious/v1/04_Field_Types.md b/en/03_Formalicious/v1/04_Field_Types.md index 3822d2df..9985b845 100755 --- a/en/03_Formalicious/v1/04_Field_Types.md +++ b/en/03_Formalicious/v1/04_Field_Types.md @@ -1,3 +1,7 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + A form consists of fields. These fields can be categorised by type. Formalicious is shipped with the most common field-types by default: * Checkboxes @@ -35,4 +39,4 @@ Below is an example of our "Special email Tpl" (copy of emailTpl): **And that's it, you're all set!** -![The new field in action](../images/createfieldexample.png) \ No newline at end of file +![The new field in action](../images/createfieldexample.png) diff --git a/en/03_Formalicious/v1/05_Create_a_Form.md b/en/03_Formalicious/v1/05_Create_a_Form.md index 5ffa9537..4472e44c 100755 --- a/en/03_Formalicious/v1/05_Create_a_Form.md +++ b/en/03_Formalicious/v1/05_Create_a_Form.md @@ -1,3 +1,7 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + Creating a form is something you can do yourself, as a MODX website maintainer, but Formalicious enables content-manager to also create forms. The process of setting up a Formalicious-form can be split into 3 steps. Each step has a Tab in the create-form dialog: @@ -31,7 +35,7 @@ You have to save the form settings before you can access this tab and add steps/ Before adding a field, you need to add a _Step_. You can change the text of a _Step_ by double clicking the text of the step. It will allow you to change the text inline. Hit _Enter_ to save the changes. -Steps will group your from fields on the frontend and next/previous buttons will be automatically added by Formalicious for your users. The only thing you have to do is styling! +Steps will group your from fields on the frontend and next/previous buttons will be automatically added by Formalicious for your users. The steps are also available as navigation on the frontend via `[[!+formalicious.navigation]]` ## Form fields Every step can contain fields. Click 'Add field' and choose a field type in the dialog window. This will open the "Save field" dialog. The title will be the label of the field, the placeholder is optional and works as a [HTML5 Placeholder attribute](https://www.w3.org/TR/html5/forms.html#the-placeholder-attribute). @@ -46,4 +50,4 @@ Now is the time to put a form on a page! This can be done by going to a page and ![Select a Formalicious form in a page](../images/resource.png) -Alternatively, if you use [ContentBlocks](https://www.modmore.com/contentblocks/), you can also create a _Formalicious Form Selector_ field and insert that into your page. +Alternatively, if you use [ContentBlocks](https://modmore.com/contentblocks/), you can also create a _Formalicious Form Selector_ field and insert that into your page. diff --git a/en/03_Formalicious/v1/06_FAQs.md b/en/03_Formalicious/v1/06_FAQs.md index 13caa278..517bb759 100755 --- a/en/03_Formalicious/v1/06_FAQs.md +++ b/en/03_Formalicious/v1/06_FAQs.md @@ -1,5 +1,11 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + We're collecting the questions we get most often into a list of FAQs. If your question is not in the list, please reach out to us via support@modmore.com and we would be glad to help. +[TOC] + ## How do I show my created form? Make sure that you marked your form as Published, and then add the following snippet call where you want the form to appear (without the spaces): @@ -16,3 +22,10 @@ This can be accomplished by going to the creating (or editing) a field-type in t Everything is customisable by using chunks or FormIt parameters. First, create a duplicate of the email-chunk (emailFormTpl or fiarTpl) you wish to change and rename it. Then go to the form which should use this new chunk. Go to the _Advanced_ section and click _Add parameter_. Set the parameter-key to _emailTpl_ or _fiarTpl_ and set the value to the chunk you just made. + +## Adding a reply to address + +If you'd like the emails to have the proper reply-to header set, so you can immediately reply to an email to the customer, you can add a custom parameter to your form. + +Edit your form. On the Advanced tab, add a custom parameter with paramater key `emailReplyTo` and a value of `[[+field_ID]]`, where `ID` is the ID of the field that contains your customers' email address. You can find that ID on the Form Fields tab, in the first column. For example if your email field has ID 5, you would set the value to `[[+field_5]]`. + diff --git a/en/03_Formalicious/v1/07_Special_Fields/Math.md b/en/03_Formalicious/v1/07_Special_Fields/Math.md new file mode 100644 index 00000000..6f743bd7 --- /dev/null +++ b/en/03_Formalicious/v1/07_Special_Fields/Math.md @@ -0,0 +1,42 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + + +To prevent spam, you can use the [Math hook](https://docs.modx.com/extras/revo/formit/formit.hooks/formit.hooks.math) that ships with FormIt. + +[TOC] + +## Create a custom field + +Go to Extras > Formalicious and click on Admin Panel in the top right. On the _Field Types_ tab, create a new field type, providing the following information: + +- Name: a name of your choosing to describe the field, for example `Math Captcha` +- Chunk Template: `customMathFieldTpl` (we'll create this chunk momentarily) +- Leave the values question unchecked and define no chunk for values +- Leave validators empty as well. While the Math hook docs mention making the math field required, that does not work by specifying the validator on the field type in Formalicious. (Formalicious uses `field_ID` names for the fields, while the Math hook expects a hardcoded `math` field) + +Save, and create a new chunk called `customMathFieldTpl` with the following: + +````html +
+
+ + [[!+fi.error.math]] + +
+
+```` + +Now you're ready to use the field. + +## Add the field to a form + +Go to Extras > Formalicious and edit your form. + +Add the newly created `Math Captcha` field to your form. You can give it a title, but that's not currently used in the `customMathFieldTpl`, so is only shown in the form management. + +Next open the Advanced tab, and add `math` to the Posthooks. This makes sure the field is validated and that error messages are shown. + +**Important**: the math hook only works with forms that only have a single step. + diff --git a/en/03_Formalicious/v1/index.md b/en/03_Formalicious/v1/index.md index db5c1db7..53f6bc4e 100644 --- a/en/03_Formalicious/v1/index.md +++ b/en/03_Formalicious/v1/index.md @@ -1,9 +1,13 @@ --- title: Formalicious -description: Documentation for Formalicious, a premium form builder for MODX by Sterc. +description: Documentation for Formalicious, a premium form builder for MODX by Sterc. --- -[Formalicious](https://www.modmore.com/formalicious/) is the most powerful and easiest MODX form builder, with built-in multi-step forms, 8 field types, validation and the ability to use hooks and other advanced FormIt features. +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +[Formalicious](https://modmore.com/formalicious/) is the most powerful and easiest MODX form builder, with built-in multi-step forms, 8 field types, validation and the ability to use hooks and other advanced FormIt features. # Recommended Reading diff --git a/en/03_Formalicious/v2/01_Installation.md b/en/03_Formalicious/v2/01_Installation.md new file mode 100755 index 00000000..c7702255 --- /dev/null +++ b/en/03_Formalicious/v2/01_Installation.md @@ -0,0 +1,24 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +Installing Formalicious requires the free Extra _FormIt 4.1.1-pl_ to function properly. FormIt is also maintained by us and thus, should guarantee maximum compatibility between FormIt and Formalicious. The MODX installer should install this automatically when installing Formalicious from the modmore repository. + +A custom manager page called _Formalicious_ is installed within the _Extras_ menu. Also a Template Variable and Element Category named _Formalicious_ are created. The _Template Variable_ should be assigned to all the templates you wish to use Formalicious forms on and a Snippet should be added to those templates. +Access to Formalicious and the admin panel can be set at the modx ACL access policies. + +To accomplish this, follow these steps: +1. Click the _formalicious_ TV +2. Click _Template Access_ +3. Enable the checkmarks for the templates on which you want to use Formalicious-forms +4. Save your changes +5. Go to every template you just enabled +6. In the field _Template code (HTML)_, add the following Snippet-call at the location where you want to show your forms: ```[[!FormaliciousRenderForm? &form=`[[*formalicious]]`]]``` We recommend to add it just below the ```[[*content]]``` placeholder, because it enables your content-managers to add text above the form. +7. An alternative would be to create a chunk called _form_ where you add the above Snippet-call. Instruct your content-managers to add the chunk-code ```[[$form]]``` anywhere they want, so they have more flexibility regarding the location of their forms, e.g. in-between two paragraphs. +8. Save your changes + +## Inserting a form with ContentBlocks + +If you also use [ContentBlocks](https://www.modmore.com/contentblocks/), you can use a field to select a form to insert as well, instead of needing the template variable and form code in your template. This gives your content editors more control over what form is inserted at what position. + +Formalicious will add its custom input type during installation. At Extras > ContentBlocks, create a new field using the "Formalicious Form Selector" input type and customise the template as needed. diff --git a/en/03_Formalicious/v2/02_Media_Sources.md b/en/03_Formalicious/v2/02_Media_Sources.md new file mode 100755 index 00000000..45e7563b --- /dev/null +++ b/en/03_Formalicious/v2/02_Media_Sources.md @@ -0,0 +1,9 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +Formalicious contains one _System Setting_: `formalicious.source`, which defaults to `1`. This is the default _Filesystem_ media source. + +Set this to the media source ID you wish to use when selecting email-attachments for auto-replies. + +You can find an overview of all your media sources by clicking _Media Sources_ in the _Media_ menu. The first column in the media sources table can be used as the ID of the `formalicious.source` setting. diff --git a/en/03_Formalicious/v2/03_Categories.md b/en/03_Formalicious/v2/03_Categories.md new file mode 100755 index 00000000..fa984d3f --- /dev/null +++ b/en/03_Formalicious/v2/03_Categories.md @@ -0,0 +1,9 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +Organising your forms from the start is highly recommended. You can do this by creating Form Categories. Categories allow you to group forms into tabs. + +Create tabs by going to the Formalicious page in the Extras-menu and click on _Admin panel_. + +Manage your _Categories_ in the first tab. The category-name will be displayed as the tab-name, followed by the description, which can be used to explain to your users what the category is used for. diff --git a/en/03_Formalicious/v2/04_Field_Types.md b/en/03_Formalicious/v2/04_Field_Types.md new file mode 100755 index 00000000..20fdcde5 --- /dev/null +++ b/en/03_Formalicious/v2/04_Field_Types.md @@ -0,0 +1,63 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +A form consists of fields. These fields can be categorised by type. Formalicious is shipped with the most common field-types by default: + +* Checkboxes +* Email +* File +* Number +* Radiobuttons +* Select +* Text +* Textarea + +All these types have a _Chunk_ associated with them. These can be found in the Elements-tree, below the Formalicious-category. These chunks are optimised for [Bootstrap](http://getbootstrap.com/) + +All the required fields are implemented in Formalicious, but you can change these chunks to match your needs. **It is recommended to duplicate and rename a field before changing it**, because an update of Formalicious will override the original chunks. + +## Creating your own field type +We made the most common used input fields already available, but we offer creative freedom here. You can create your own types with your own chunks. + +The following placeholders can be used + +| placeholder | description | +|-------------------|------------------------------------------------------------------------------------| +| [[!+name]] | Name of the field. | +| [[!+title]] | Title of the field, used for show. | +| [[!+value]] | Data filled in form when submitted. | +| [[!+description]] | Extra description for your field. | +| [[!+placeholder]] | The placeholder attribute for your field, can also be used in different varieties. | +| [[!+error]] | Is filled when error handling is triggered for a required field or validation. | +| [[!+values]] | Contains the options for radio/checkboxes. | + +### Step 1: Create the type +Create your type and enter a _Name_ and _Tpl_. The _Value Tpl_ field is only to determine your options for checkbox and radiobutton fields. + +The _Validation_ field can be used to use [FormIt validators](https://docs.modx.com/extras/revo/formit/formit.validators). + +In the example below we create a field called "Special email", with the template "specialEmailTpl": + +![specialEmailTpl Formalicious field-type](../images/createfield.png) + + +### Step 2: Create the associated chunk +We specified the chunk called "specialEmailTpl". This chunk is a regular FormIt-chunk. Please check the [FormIt tutorials](https://docs.modx.com/extras/revo/formit/formit.tutorials-and-examples/) for all your options. + +Below is an example of our "Special email Tpl" (copy of emailTpl): + +``` +
+ +
+ + [[!+error]] +
+ [[!+description:notempty=`
[[!+description]]
`]] +
+``` + +**And that's it, you're all set!** + +![The new field in action](../images/createfieldexample.png) diff --git a/en/03_Formalicious/v2/05_Create_a_Form.md b/en/03_Formalicious/v2/05_Create_a_Form.md new file mode 100755 index 00000000..6a9d2335 --- /dev/null +++ b/en/03_Formalicious/v2/05_Create_a_Form.md @@ -0,0 +1,53 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +Creating a form is something you can do yourself, as a MODX website maintainer, but Formalicious enables content-manager to also create forms. + +The process of setting up a Formalicious-form can be split into 3 steps. Each step has a Tab in the create-form dialog: +1. Form settings +2. Form fields +3. Advanced + +### Form settings + +General form-settings are modified here. + +**Important:** When creating a form, you first have to finish the _Form settings_ and save your form before being able to continue to the _Form Fields_ tab. + + +- Title: A recognisable name, for internal usage only. Won't be shown on the website itself. +- Email header text: This message will be displayed in the email sent to the email address specified in **Email to**. +- Email to: This email address will receive the submitted form entries. +- Subject: Subject of the email +- Redirect to: Resource ID where the visitor is sent to after the form is successfully submitted. +- Save submitted form: Check this to save the form into FormIt using the [FormItSaveForm hook](https://docs.modx.com/extras/revo/formit/formit.hooks/formit.hooks.formitsaveform); a great way to have a backup of all your submitted forms. +- Published: Check this to make this form available throughout the manager. +- Send auto reply: Check this to enable auto replies for this mail. The visitor who submits your form, will also receive a confirmation mail (auto reply). This is a good way to inform your visitors that a form actually worked and action is taken. _This will only work if you enter the fields below._ +- Select email field: Select the form-field where the auto-reply should be sent to. This dropdown is automatically populated by all your fields. This means you have to add your fields first and then you select an email field you wish to use as your auto-reply field. +- Email from: The sender of the auto-reply. Your website-visitor will se this in the From-field when reading the email. +- Subject: Subject of the auto-reply email. +- Content: Content of the auto-reply email. Feel free to use HTML here, but keep it limited to simple tags like: ```

``` +- Attachment: (optional) If you want to attach a file to the confirmation email, you can do it here. Bigger files mean a bigger chance of failure when sending an email. + +## Form steps +You have to save the form settings before you can access this tab and add steps/fields. + +Before adding a field, you need to add a _Step_. You can change the text of a _Step_ by double clicking the text of the step. It will allow you to change the text inline. Hit _Enter_ to save the changes. + +Steps will group your from fields on the frontend and next/previous buttons will be automatically added by Formalicious for your users. The only thing you have to do is styling! + +## Form fields +Every step can contain fields. Click 'Add field' and choose a field type in the dialog window. This will open the "Save field" dialog. The title will be the label of the field, the placeholder is optional and works as a [HTML5 Placeholder attribute](https://www.w3.org/TR/html5/forms.html#the-placeholder-attribute). + +Every field has two extra options: _Required_ will make a field mandatory. _Published_ allows you to disable a field (temporary). + +## Advanced +In the Advanced tab you can add FormIt prehooks, posthooks and custom parameters. More on that can be found on the [FormIt docs (hooks section)](https://docs.modx.com/extras/revo/formit/formit.hooks). + +## Getting your form in a page +Now is the time to put a form on a page! This can be done by going to a page and select a template you assigned the _formalicious_ Template Variable to. From there, select the Formalicious form you wish to show on that page. + +![Select a Formalicious form in a page](../images/resource.png) + +Alternatively, if you use [ContentBlocks](https://www.modmore.com/contentblocks/), you can also create a _Formalicious Form Selector_ field and insert that into your page. diff --git a/en/03_Formalicious/v2/06_FAQs.md b/en/03_Formalicious/v2/06_FAQs.md new file mode 100755 index 00000000..8c8cec3f --- /dev/null +++ b/en/03_Formalicious/v2/06_FAQs.md @@ -0,0 +1,34 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +We're collecting the questions we get most often into a list of FAQs. If your question is not in the list, please reach out to us via support@modmore.com and we would be glad to help. + +[TOC] + +## How do I show my created form? +Make sure that you marked your form as Published, and then add the following snippet call where you want the form to appear (without the spaces): + +```` html +[[!FormaliciousRenderForm? &form=`FORM ID HERE`]] +```` + +You can also use a template variable to select the form, and to place the template variable value in the form property. + +## I want to setup custom validation per field +This can be accomplished by going to the creating (or editing) a field-type in the admin-panel. You can mention a comma-separated list of FormIt-validators in the _Validation_ field in the dialog-window. + +## I don't like the emails sent by Formalicious +Everything is customisable by using chunks or FormIt parameters. First, create a duplicate of the email-chunk (emailFormTpl or fiarTpl) you wish to change and rename it. Then go to the form which should use this new chunk. + +Go to the _Advanced_ section and click _Add parameter_. Set the parameter-key to _emailTpl_ or _fiarTpl_ and set the value to the chunk you just made. + +## Adding a reply to address + +If you'd like the emails to have the proper reply-to header set, so you can immediately reply to an email to the customer, you can add a custom parameter to your form. + +Edit your form. On the Advanced tab, add a custom parameter with paramater key `emailReplyTo` and a value of `[[+field_ID]]`, where `ID` is the ID of the field that contains your customers' email address. You can find that ID on the Form Fields tab, in the first column. For example if your email field has ID 5, you would set the value to `[[+field_5]]`. + +## Updating to v2 +Updating is only possible from the v1.4.4 version but still needs you to refactor some fields & tpls. +The new snippet & placeholder names can be found in the instructions. diff --git a/en/03_Formalicious/v2/07_Special_Fields/Math.md b/en/03_Formalicious/v2/07_Special_Fields/Math.md new file mode 100644 index 00000000..aacf5ab3 --- /dev/null +++ b/en/03_Formalicious/v2/07_Special_Fields/Math.md @@ -0,0 +1,41 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +To prevent spam, you can use the [Math hook](https://docs.modx.com/extras/revo/formit/formit.hooks/formit.hooks.math) that ships with FormIt. + +[TOC] + +## Create a custom field + +Go to Extras > Formalicious and click on Admin Panel in the top right. On the _Field Types_ tab, create a new field type, providing the following information: + +- Name: a name of your choosing to describe the field, for example `Math Captcha` +- Chunk Template: `customMathFieldTpl` (we'll create this chunk momentarily) +- Leave the values question unchecked and define no chunk for values +- Leave validators empty as well. While the Math hook docs mention making the math field required, that does not work by specifying the validator on the field type in Formalicious. (Formalicious uses `field_ID` names for the fields, while the Math hook expects a hardcoded `math` field) + +Save, and create a new chunk called `customMathFieldTpl` with the following: + +````html +
+
+ + [[!+fi.error.math]] + +
+
+```` + +Now you're ready to use the field. + +## Add the field to a form + +Go to Extras > Formalicious and edit your form. + +Add the newly created `Math Captcha` field to your form. You can give it a title, but that's not currently used in the `customMathFieldTpl`, so is only shown in the form management. + +Next open the Advanced tab, and add `math` to the Posthooks. This makes sure the field is validated and that error messages are shown. + +**Important**: the math hook only works with forms that only have a single step. + diff --git a/en/03_Formalicious/v2/10_upgrades/v2.0.0.md b/en/03_Formalicious/v2/10_upgrades/v2.0.0.md new file mode 100644 index 00000000..c51c524c --- /dev/null +++ b/en/03_Formalicious/v2/10_upgrades/v2.0.0.md @@ -0,0 +1,39 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +--- +title: v2.0.x +--- +Most upgrades are automatically applied, but sometimes you may need to update custom templates, or status configuration, to take advantage of new features or improvements. Those changes are discussed here. + +## File based +All default chunks except the field types are being processed file based. +This means that some chunks can't be accessed via the elements in the manager. + +## Naming +Some changes have been made in the naming of snippets, chunks and some placeholders to prevent overwrite off custom chunks & snippets. +All default snippets & chunks are prefixed with Formalicious. +Example: RenderForm is now FormaliciousRenderForm + +Changed placeholders: + +| old | new | location | +|------------------------|------------------|-----------------------| +| [[!+fieldname]] | [[!+name]] | All field type chunks | +| [[+fieldsemailoutput]] | [[+emailFields]] | email.chunk.tpl | +| [[+fieldsemailoutput]] | [[+fiarFields]] | fiaremail.chunk.tpl | + +## Permissions +Version 2.0.x now has permissions to manage access to parts of the form management. +- formalicious_admin to show/hide admin panel +- formalicious_tab_fields to show/hide fields tab +- formalicious_tab_advanced to show/hide advanced tab + +## Navigation (Steps) +A navigation is now available form the form steps set in the form builder via the following placeholder `[[!+formalicious.navigation]]`. The default styling is Bootstrap. + +## FormIt +FormIt 4.1.1 is required for V2.0.x to work and will automatically be installed when installing V2.0.x + +FormIt parameters used to be within the form.chunk.tpl however this have been replaced by the placeholder `[[!+FormItParameters]]` as custom parameters and hooks can now be set within the Formalicious form builder. diff --git a/en/03_Formalicious/v2/index.md b/en/03_Formalicious/v2/index.md new file mode 100644 index 00000000..971a5da2 --- /dev/null +++ b/en/03_Formalicious/v2/index.md @@ -0,0 +1,19 @@ +> **This extra is discontinued**. It was originally built by Sterc and distributed by modmore as a Premium Extra, however in 2020 Sterc decided they can no longer offer the support required. It is no longer available from modmore, but may be available elsewhere. +> +> Unfortunately modmore cannot provide standard support for this extra. You may request support from Sterc directly or consider [booking Premium MODX Support](https://modmore.com/premium-modx-support/) if you need help with it. + +--- +title: Formalicious +description: Documentation for Formalicious, a premium form builder for MODX by Sterc. +--- + +[Formalicious](https://www.modmore.com/formalicious/) is the most powerful and easiest MODX form builder, with built-in multi-step forms, 8 field types, validation and the ability to use hooks and other advanced FormIt features. + +V2 is updated to use the lastest modx FormIt package and allowes better handling of placeholders & styling withing your form creating. + +# Recommended Reading + +- [Installation](Installation) +- [Categories](Categories) +- [Create a Form](Create_a_Form) + diff --git a/en/03_MoreGallery/v1.x/00_User_Guide.md b/en/03_MoreGallery/v1.x/00_User_Guide.md index b8a2aa48..e10dada4 100644 --- a/en/03_MoreGallery/v1.x/00_User_Guide.md +++ b/en/03_MoreGallery/v1.x/00_User_Guide.md @@ -1,4 +1,4 @@ -This user guide is meant for the end-users of the MoreGallery add-on. For information about front-end implementation, please review the [documentation](https://www.modmore.com/moregallery/documentation/). +This user guide is meant for the end-users of the MoreGallery add-on. For information about front-end implementation, please review the [documentation](https://modmore.com/moregallery/documentation/). **Please note** that your designer or developer has the tools to customise MoreGallery to your exact needs. Because of that, not all information in this document may apply to your specific situation. @@ -25,7 +25,7 @@ Uploading images is really easy. Just click the Upload button, and choose the im After choosing images, you will see them being added to the images overview. They are still being uploaded (if the images are really big, this can take some time), but when the spinner disappears and the bar turns green, it is done. -![](https://www.modmore.com/assets/uploads/2013/mgupload3.gif) +![](https://modmore.com/assets/uploads/2013/mgupload3.gif) ## Importing Images @@ -41,7 +41,7 @@ To add a video, click the _Add Video_ button in the toolbar. In the window that To sort the images in a different order than what they were uploaded, you can drag them across the page. Click the image while holding down the mouse button, and move your mouse to where you want the image to appear. A black outline will show where the image will be placed if you release the mouse. -![](https://www.modmore.com/assets/uploads/2013/recording2.gif) +![](https://modmore.com/assets/uploads/2013/recording2.gif) ## Editing Image Information @@ -49,7 +49,7 @@ Each image has information associated with it. This includes at the very least a To edit this information, click the white bar below the image (the one with the name, filename and the modify icon). An edit pane and enlargement of the image will appear below it. -![](https://www.modmore.com/assets/uploads/2013/editimage.gif) +![](https://modmore.com/assets/uploads/2013/editimage.gif) When the edit pane opened, you can edit the information in the fields. When you are done changing the details, you can just close the edit pane with the close button; the changes are automatically saved. @@ -65,4 +65,4 @@ When hovering over an image in the main view, you can see a number of options. B To view a large version of an image in the Manager, click the small image preview. A modal window will pop up showing a large version of the image. -![](https://www.modmore.com/assets/uploads/2013/previewlarge3.gif) \ No newline at end of file +![](https://modmore.com/assets/uploads/2013/previewlarge3.gif) \ No newline at end of file diff --git a/en/03_MoreGallery/v1.x/01_Getting_Started.md b/en/03_MoreGallery/v1.x/01_Getting_Started.md index ce24be4f..b50fab18 100644 --- a/en/03_MoreGallery/v1.x/01_Getting_Started.md +++ b/en/03_MoreGallery/v1.x/01_Getting_Started.md @@ -6,9 +6,9 @@ In this getting started document we'll walk you through the basic set up for Mor ## Prerequisite: Installing MoreGallery -If you haven't yet, the first step is to install the MoreGallery. You'll need a modmore.com account and follow the instructions [found in the Purchases section of the site](https://www.modmore.com/account/purchases/). +If you haven't yet, the first step is to install the MoreGallery. You'll need a modmore.com account and follow the instructions [found in the Purchases section of the site](https://modmore.com/account/purchases/). -On a local development domain, you may use a [free development license](https://www.modmore.com/free-development-licenses/). Otherwise you'll need to buy a license first as well. +On a local development domain, you may use a [free development license](https://modmore.com/free-development-licenses/). Otherwise you'll need to buy a license first as well. ## Step 1: Create a Gallery Resource diff --git a/en/03_MoreGallery/v1.x/Snippets/00_mgGetImages.md b/en/03_MoreGallery/v1.x/03_Snippets/00_mgGetImages.md similarity index 61% rename from en/03_MoreGallery/v1.x/Snippets/00_mgGetImages.md rename to en/03_MoreGallery/v1.x/03_Snippets/00_mgGetImages.md index b0e64c29..4d7757bf 100644 --- a/en/03_MoreGallery/v1.x/Snippets/00_mgGetImages.md +++ b/en/03_MoreGallery/v1.x/03_Snippets/00_mgGetImages.md @@ -14,60 +14,82 @@ The minimum mgGetImages snippet call outputs a list of thumbnails, linking to an You should always call mgGetImages uncached, as it manages caching internally. This makes sure the images on a Gallery resource are in sync with the frontend, without relying on full site cache clears. +## Listing & single image views + +The `mgGetImages` snippet by default lists images in a gallery, but it also supports a "single image view" or "detail view". When the page is requested with a `iid` URL parameter (or another parameter defined by the `&singleImageParam` snippet parameter), only the specific image is shown with the `&singleImageTpl`. + +The single image view also includes previous and next images, so it can be used for a simple gallery view without any JavaScript solutions. This detail view is also used to render embed codes for videos and iframes for PDFs. The detail view can also be disabled with `&singleImageEnabled`. + +The parameter for the rendering of one image in the list is `&imageTpl`, not `&singleImageTpl`. + ## Snippet Properties -#### &resource +#### &resource + +The ID of the MoreGallery resource to get images from. By default, this will use the current resource, so you wont need to specify this if you want to show images from the current resource. + +As of 1.5.0, you can also specify a comma separated list of resource IDs to get images from. This is best used in combination with a `&sortBy` of `uploadedon` or `random`. + +**Default**: current resource ID + +#### &images -The ID of the MoreGallery resource to get images from. By default, this will use the current resource, so you wont need to specify this if you want to show images from the current resource. +Provide a comma separated list of image IDs to only return those images. This overrides the `&resource` property. -As of 1.5.0, you can also specify a comma separated list of resource IDs to get images from. This is best used in combination with a `&sortBy` of `uploadedon` or `random`. +Meant to be used with the [Image Selector](../Image_Selector) and `` &sortBy=`selection` `` to return images in the order they were selected. -**Default**: current resource ID +Added in v1.16. + +**Default**: none #### &sortBy -The field to sort images on. This can be one of the following: `filename`, `name`, `sortorder`, `uploadedon`, `editedon` or `random` to randomise the order of the images. +The field to sort images on. This can be one of the following: `id`, `filename`, `name`, `sortorder`, `uploadedon`, `editedon` or `random` to randomise the order of the images. + +As of v1.16.0, you can also use `selection` in combination with an `&images` property that provides image IDs as a comma separated list. This is intended to be used with the [Image Selector](../Image_Selector). **Default**: `sortorder` +**Note**: Sorting by `uploadedon` may not load the right previous/next images in the single image view because of identical values. This was fixed in 1.16.0; on older versions you may sort by `&id` instead to produce a similar result. + #### &sortDir -Used with the `&sortBy` property, this will decide in what direction (ASC: ascending or DESC: descending) the results will be sorted. +Used with the `&sortBy` property, this will decide in what direction (ASC: ascending or DESC: descending) the results will be sorted. -**Default**: `ASC` +**Default**: `ASC` #### &tags -Specify a comma separated list of tag names or IDs to filter the resulting images on. +Specify a comma separated list of tag names or IDs to filter the resulting images on. -To find images that are _not_ tagged with a certain tag, you can specify it with a dash in front (e.g. `-highlight`) since 1.4.0. +To find images that are _not_ tagged with a certain tag, you can specify it with a dash in front (e.g. `-highlight`) since 1.4.0. -While similar in naming, has no relation to `&getTags`. If you would like to accept tags through an URL parameter, you can do so with the `&tagsFromUrl` property. Added in 1.1.0. +While similar in naming, has no relation to `&getTags`. If you would like to accept tags through an URL parameter, you can do so with the `&tagsFromUrl` property. Added in 1.1.0. -**Default**: +**Default**: #### &tagsFromUrl -When not empty, the snippet will look for an URL parameter with the specified name (so if you set this property to "tag" it will look for an URL parameter called "tag") and filter image results on the value of that parameter, which can be a tag ID or actual tag display name. Added in 1.1.0. +When not empty, the snippet will look for an URL parameter with the specified name (so if you set this property to "tag" it will look for an URL parameter called "tag") and filter image results on the value of that parameter, which can be a tag ID or actual tag display name. Added in 1.1.0. #### &getTags -Set to `1` to load tags for each image and to parse them through the chunk specified in the `&tagTpl` property. +Set to `1` to load tags for each image and to parse them through the chunk specified in the `&tagTpl` property. -The result of parsing tags through &tagTpl and separated by the value in `&tagSeparator` will be set to the `[[+tags]]` placeholder in both chunks for `&imageTpl` and `&singleImageTpl`. For added performance, disable this property by setting it to `0` when not using tags. +The result of parsing tags through &tagTpl and separated by the value in `&tagSeparator` will be set to the `[[+tags]]` placeholder in both chunks for `&imageTpl` and `&singleImageTpl`. For added performance, disable this property by setting it to `0` when not using tags. -Added in 1.1.0. +Added in 1.1.0. **Default**: 1 #### &getResourceFields Set to `1` to make resource fields available in the `&imageTpl` and `&singleImageTpl` chunks. - -The resource fields will be made available as placeholders prefixed by "resource". For example `[[+resource.pagetitle]]`. -When calling mgGetImages on the Gallery resource itself, this isn't typically needed as you could just use the `[[*pagetitle]]` resource fields, but with [multiple galleries](../Multiple_Galleries) this is useful to enable. +The resource fields will be made available as placeholders prefixed by "resource". For example `[[+resource.pagetitle]]`. + +When calling mgGetImages on the Gallery resource itself, this isn't typically needed as you could just use the `[[*pagetitle]]` resource fields, but with [multiple galleries](../Multiple_Galleries) this is useful to enable. Added in 1.0.1. @@ -83,25 +105,33 @@ Set to `1` to also load the resource properties into the `[[+resource.properties Set to a comma separated list of TV names to make available in the `&imageTpl` and `&singleImageTpl` chunks. `&getResourceFields` needs to be set to 1 for this property to work. -The TVs will be made available as placeholders prefixed by "resource". For example for a TV called "superlongtitle", the placeholder would be `[[+resource.superlongtitle]]`. +The TVs will be made available as placeholders prefixed by "resource". For example for a TV called "superlongtitle", the placeholder would be `[[+resource.superlongtitle]]`. -When calling mgGetImages on the Gallery resource this isn't typically needed as you could just use the `Snippet: mgGetImages` resource fields, but with [multiple galleries](../Multiple_Galleries) this is useful to enable. +When calling mgGetImages on the Gallery resource this isn't typically needed as you could just use the `Snippet: mgGetImages` resource fields, but with [multiple galleries](../Multiple_Galleries) this is useful to enable. -Added in 1.0.1. +Added in 1.0.1. #### &imageTpl -The name of a chunk to use for each image in the result set. +The name of a chunk to use for each image in the result set. The default chunk used is this: -**See further down this page for the default and placeholders for this chunk.** +````html +
  • + + [[+name]] + +
  • +```` + +**See further down this page for a description of all placeholders available for this chunk.** -Individual images will be joined together by the value of the `&imageSeparator` property. +Individual images will be joined together by the value of the `&imageSeparator` property. -If you're using [videos](../Video) in MoreGallery, you also need the `&youtubeTpl` and `&vimeoTpl` properties. They follow the same structure as the `&imageTpl`, but which are are applied to YouTube and Vimeo video records respectively. See below. +If you're using [videos](../Video) in MoreGallery, you also need the `&youtubeTpl` and `&vimeoTpl` properties. They follow the same structure as the `&imageTpl`, but which are are applied to YouTube and Vimeo video records respectively. For PDFs, `&pdfTpl` is available. See below. #### &mediaTpl -The name of a chunk to use for each image imported from Sterc's Media Manager. If not specified, this will use the same chunk as provided in the `&imageTpl`. +The name of a chunk to use for each image imported from Sterc's Media Manager. If not specified, this will use the same chunk as provided in the `&imageTpl`. You can use the same placeholders as the `&imageTpl`, but you can also use the following placeholders that are specific to Sterc's media manager: @@ -125,51 +155,106 @@ You can use the same placeholders as the `&imageTpl`, but you can also use the f The name of a chunk to use for templating a [YouTube video](../Video). Works identical to `&imageTpl` for videos from YouTube. +The default chunk used is: + +````html +
  • + + [[+name:htmlent]] + +
  • +```` + +If you want the video embedded, you can use something like this: + +````html +
  • +
    + +
    +
  • +```` + #### &vimeoTpl -The name of chunk to use for templating a [Vimeo video](../Video). Works identical to `&imageTpl` for videos from Vimeo. +The name of chunk to use for templating a [Vimeo video](../Video). Works identical to `&imageTpl` for videos from Vimeo. + +The default chunk used looks like this: + +````html +
  • + [[- If you want to show the Vimeo video directly, you use something like this: +
    + +
    + Otherwise, the file_url and mgr_thumb contain the thumbnail for the video. ]] + + + [[+name:htmlent]] + +
  • +```` + +If you prefer embedding the video directly, you can use something like this: + +````html +
  • +
    + +
    +
  • +```` + +#### &pdfTpl + +The name of chunk to use for templating a PDF file. Works identical to `&imageTpl`. The `[[+mgr_thumb]]` placeholder and crops will contain an image of the first page of the PDF, while `[[+file_url]]` will be a link to the actual PDF. + +When no chunk is specified, the `&imageTpl` is used by default. #### &imageSeparator -A string to be used between images parsed through the chunk specified in `&imageTpl`. +A string to be used between images parsed through the chunk specified in `&imageTpl`. -**Default**: linebreak (`\n`) +**Default**: linebreak (`\n`) #### &tagTpl -The name of a chunk to use for each tag for each image, only if `&getTags` is enabled. Individual tags will be joined together by the value of the `&tagSeparator` property. The default chunk is stored in the filesystem to prevent changes which are overwritten on upgrade, but looks like this: +The name of a chunk to use for each tag for each image, only if `&getTags` is enabled. Individual tags will be joined together by the value of the `&tagSeparator` property. The default chunk is stored in the filesystem to prevent changes which are overwritten on upgrade, but looks like this: ```` html [[+display]] - + ```` -This generates links to the current resource, passing along a "tag" URL parameter. +This generates links to the current resource, passing along a "tag" URL parameter. -If the mgGetImages snippet call has &tagsFromUrl=`tag` added, that will filter the image results based on the tag. +If the mgGetImages snippet call has &tagsFromUrl=`tag` added, that will filter the image results based on the tag. -Placeholders in the tagTpl are `[[+id]]`, `[[+display]]` (the tag itself), `[[+createdon]]` (the first time the tag was added to an image) and `createdby` (the user ID of the user that used the tag the first time). +Placeholders in the tagTpl are `[[+id]]`, `[[+display]]` (the tag itself), `[[+createdon]]` (the first time the tag was added to an image) and `createdby` (the user ID of the user that used the tag the first time). Added in 1.1.0. #### &tagSeparator -A string to be used between tags parsed through the chunk specified in `&tagTpl`. Added in 1.1.0. +A string to be used between tags parsed through the chunk specified in `&tagTpl`. Added in 1.1.0. -**Default**: linebreak (`\n`) +**Default**: linebreak (`\n`) #### &singleImageEnabled -Set to `1` to enable the single image view, or `0` to disable it. When enabled, the snippet will automatically show a single image with a different template (see `&singleImageTpl`) if the `&singleImageParam` is present in the URL. Useful for accessible image galleries. The single image view has been available since v1.0, the singleImageEnabled property was added in v1.4. +Set to `1` to enable the single image view, or `0` to disable it. When enabled, the snippet will automatically show a single image (detail view) with a different template (see `&singleImageTpl`) if the `&singleImageParam` is present in the URL. Useful for accessible image galleries. The single image view has been available since v1.0, the singleImageEnabled property was added in v1.4. -**Default**: `1` +**Default**: `1` #### &singleImageParam -The URL param to use for the single image view. This will contain the ID of an image inside the gallery that needs to be shown with the `&singleImageTpl` chunk. The single image view has been available since v1.0, but this property was added in v1.4. This setting inherits from the `moregallery.single_image_url_param` setting if left empty. +The URL param to use for the single image view. This will contain the ID of an image inside the gallery that needs to be shown with the `&singleImageTpl` chunk. The single image view has been available since v1.0, but this property was added in v1.4. This setting inherits from the `moregallery.single_image_url_param` setting if left empty. -**Default**: `iid` +**Default**: `iid` #### &singleImageResource @@ -181,80 +266,171 @@ Added in 1.5.0. #### &singleImageTpl -The name of a chunk to use for the single image view. See further down this page for the default and placeholders for this chunk. +The name of a chunk to use for the single image (/detail) view. See further down this page for the default and placeholders for this chunk. -There are also `&singleYoutubeTpl` and `&singleVimeoTpl` properties for [YouTube and Vimeo videos](../Video) respectively, which both follow the same behaviour as the `&singleImageTpl`. +**For rendering of one image in the gallery listing, see `&imageTpl` instead.** + +There are also `&singleYoutubeTpl` and `&singleVimeoTpl` properties for [YouTube and Vimeo videos](../Video) respectively, and a `&singlePdfTpl` for PDFs, which both follow the same behaviour as the `&singleImageTpl`. + +The default chunk used is: + +````html +

    + + [[+name]] + +

    + +

    +[[+prev.id:notempty=` + « [[+prev.name]] +`]] + [[+name]] +[[+next.id:notempty=` + [[+next.name]] » +`]] +

    +```` #### &singleYoutubeTpl -The name of a chunk to use for a single YouTube video embed. Works identical to `&singleImageTpl` for YouTube videos. +The name of a chunk to use for a single YouTube video embed. Works identical to `&singleImageTpl` for YouTube videos. + +The default chunk used is: + +````html +
    + +
    + +

    +[[+prev.id:notempty=` + « [[+prev.name]] +`]] + [[+name]] +[[+next.id:notempty=` + [[+next.name]] » +`]] +

    +```` #### &singleVimeoTpl -The name of a chunk to use for a single Vimeo video embed. Works identical to `&singleImageTpl` for Vimeo videos. +The name of a chunk to use for a single Vimeo video embed. Works identical to `&singleImageTpl` for Vimeo videos. + +The default chunk used is: +````html +
    + +
    + +

    +[[+prev.id:notempty=` + « [[+prev.name]] +`]] + [[+name]] +[[+next.id:notempty=` + [[+next.name]] » +`]] +

    +```` + +#### &singlePdfTpl + +The name of a chunk to use for a single PDF file being shown. Works identical to the `&singleImageTpl` property. The `[[+mgr_thumb]]` and crops will contain images of the first page in the PDF, while `[[+file_url]]` is a link to the actual PDF. + +The default chunk used is: + +```html +
    + +
    + +

    +[[+prev.id:notempty=` + « [[+prev.name]] +`]] + [[+name]] +[[+next.id:notempty=` + [[+next.name]] » +`]] +

    + +``` #### &wrapperTpl -The name of a chunk to use as wrapper template. See further down this page for the default and placeholders for this chunk. +The name of a chunk to use as wrapper template. See further down this page for the default and placeholders for this chunk. #### &wrapperIfEmpty -Set to `0` to return an empty result instead of the `&wrapperTpl` chunk when there are no (matching) images. Added in v1.4. +Set to `0` to return an empty result instead of the `&wrapperTpl` chunk when there are no (matching) images. Added in v1.4. -**Default**: 1 +**Default**: 1 #### &toPlaceholder -The name of a placeholder to set the result to. When empty it will return the result directly where called. +The name of a placeholder to set the result to. When empty it will return the result directly where called. #### &totalVar -Name of a placeholder to set the total amount of images to. ([Primarily used for paginating results](../Pagination)) +Name of a placeholder to set the total amount of images to. ([Primarily used for paginating results](../Pagination)) **Default**: `total` #### &limit -The amount of images to return ([optionally per page](../Pagination)) when listing images. +The amount of images to return ([optionally per page](../Pagination)) when listing images. + +#### &randomLimit + +When using a random sort order, MoreGallery requests all images that match your filters and writes them to the cache. It then randomly picks them from the cache file on render. + +On really large galleries, this can slow down performance and increase memory usage. In particularly large cases, we've seen the process of loading all results time out or exceed allowed memory, causing it to never write the file. + +To avoid the heaviest hit, the &randomLimit property was introduced in v1.11.1 with a default of 1500 images. This means it will only ever grab 1500 images to pick a random one from. 1500 images equates +- 5 seconds of processing on an initial request, with much improved response times on subsequent requests grabbing `&limit` random images from the cache. You can tweak the number to match your scenario if you need more random results or more performance. #### &offset -Indicates starting at what index the results should be returned ([primarily used for paginating results](../Pagination)). +Indicates starting at what index the results should be returned ([primarily used for paginating results](../Pagination)). -**Note:** if you're specifying an offset, you also need to specify a limit larger than 0. This can be a crazy big amount if you want all images, but without a limit offset wont work. +**Note:** if you're specifying an offset, you also need to specify a limit larger than 0. This can be a crazy big amount if you want all images, but without a limit offset wont work. #### &scheme -The scheme to be used in url generation when the `url` field of an image is a resource ID. Defaults to the value of the `link_tag_scheme` (core) system setting. +The scheme to be used in url generation when the `url` field of an image is a resource ID. Defaults to the value of the `link_tag_scheme` (core) system setting. #### &cache -When enabled, mgGetImages will cache the images on various levels. +When enabled, mgGetImages will cache the images on various levels. -There really is no need to turn this off since 0.9.6. Changes to chunks and snippet properties are automatically recognised, causing it to regenerate the markup. +There really is no need to turn this off since 0.9.6. Changes to chunks and snippet properties are automatically recognised, causing it to regenerate the markup. -**Default**: 1 +**Default**: 1 #### &where -A JSON object for generic filtering. For example you can use this to get a specific image by passing `{"id":5}`. +A JSON object for generic filtering. For example you can use this to get a specific image by passing `{"id":5}`. #### &activeOnly -By default mgGetImages will only show active images, but if you also want hidden images to be returned you can set this property to `0`. +By default mgGetImages will only show active images, but if you also want hidden images to be returned you can set this property to `0`. -**Default**: 1 +**Default**: 1 #### &debug -When set to `1`, MoreGallery will output a debug log showing how it processed the snippet call and ended up with the results it showed. This debug information is appended to the output of the snippet. +When set to `1`, MoreGallery will output a debug log showing how it processed the snippet call and ended up with the results it showed. This debug information is appended to the output of the snippet. #### &timing -When set to `1`, MoreGallery will output the total time it took to process the snippet. This will be appended to the end of the snippet. Useful when combined with `&debug` to identify performance bottlenecks. +When set to `1`, MoreGallery will output the total time it took to process the snippet. This will be appended to the end of the snippet. Useful when combined with `&debug` to identify performance bottlenecks. -The expected timing for a cached result (so a repeat request) is expected to be around 5-10ms, while the uncached result strongy depends on the number of images that are loaded and the complexity of your templates. +The expected timing for a cached result (so a repeat request) is expected to be around 5-10ms, while the uncached result strongy depends on the number of images that are loaded and the complexity of your templates. --- @@ -278,9 +454,9 @@ Before v1.5, this used to be: ```` -To show the image, the main placeholders to use are `[[+file_url]]`, `[[+file_path]]` in combination with a thumbnail snippet like pthumb, `[[+view_url]]` for the single image view, or `[[+mgr_thumb]]` for the thumbnail also used in the manager. +To show the image, the main placeholders to use are `[[+file_url]]`, `[[+file_path]]` in combination with a thumbnail snippet like pthumb, `[[+view_url]]` for the single image view, or `[[+mgr_thumb]]` for the thumbnail also used in the manager. -[When using video](../Video) the `[[+video_id]]` placeholder contains the unique video ID for the service that can be used to create an embed code to suit your needs. The `[[+service]]` placeholder contains either `youtube` or `vimeo`. The chunk names for video are specified in either the `&youtubeTpl` or `&vimeoTpl` properties. +[When using video](../Video) the `[[+video_id]]` placeholder contains the unique video ID for the service that can be used to create an embed code to suit your needs. The `[[+service]]` placeholder contains either `youtube` or `vimeo`. The chunk names for video are specified in either the `&youtubeTpl` or `&vimeoTpl` properties. Our [Demo Site](http://demo.modmore.com/) contains an example implementation of MoreGallery. @@ -288,39 +464,39 @@ The placeholders you can use in the chunks for `&imageTpl`, `&youtubeTpl`, `&vim #### [[+idx]] -The index of the image in the total set. +The index of the image in the total set. -**Example**: `1` +**Example**: `1` #### [[+id]] -The ID of the image. +The ID of the image. -**Example**: `64` +**Example**: `64` #### [[+filename]] -The filename of the originally uploaded image. MoreGallery prepends the image ID to a filename when uploading, however this field does not include that. +The filename of the originally uploaded image. MoreGallery prepends the image ID to a filename when uploading, however this field does not include that. -**Example**: `my-beautiful-image.png` +**Example**: `my-beautiful-image.png` #### [[+file]] -The actual filename, relative to the location of the configured media source and this gallery its folder. +The actual filename, relative to the location of the configured media source and this gallery its folder. -**Example**: `64_my-beautiful-image.png` +**Example**: `64_my-beautiful-image.png` #### [[+file_url]] -A fully qualified url to the image based on the configured media source. +A fully qualified url to the image based on the configured media source. -**Example**: `/assets/galleries/6/64_my-beautiful-image.png` +**Example**: `/assets/galleries/6/64_my-beautiful-image.png` #### [[+file_path]] -A fully qualified path to the image based on the configured media source. +A fully qualified path to the image based on the configured media source. -**Example**: `/home/user/public_html/assets/galleries/6/64_my-beautiful-image.png` +**Example**: `/home/user/public_html/assets/galleries/6/64_my-beautiful-image.png` #### [[+mgr_thumb]] @@ -328,35 +504,35 @@ A fully qualified url to a resized thumbnail used in the manager, retaining the #### [[+width]] -The width of the uploaded image in pixels. Added in v1.3 +The width of the uploaded image in pixels. Added in v1.3 #### [[+height]] -The height of the uploaded image in pixels. Added in v1.3 +The height of the uploaded image in pixels. Added in v1.3 #### [[+uploadedon]] -The time, as defined by an integer unix timestamp, that the image was added to the gallery. Can be formatted into a user-readable date with the `date` output filter. +The time, as defined by an integer unix timestamp, that the image was added to the gallery. Can be formatted into a user-readable date with the `date` output filter. #### [[+uploadedby]] The ID of the MODX User Account that added the image to the gallery. This can be used with the `userinfo` output filter to show information about that user, for example: - + ```` [[+uploadedby:userinfo=`username`]] ```` #### [[+editedon]] -The time, as defined by an integer unix timestamp, that the image was last edited. Note that dragging an image across the gallery may affect the editedon date for a large part of the gallery. - +The time, as defined by an integer unix timestamp, that the image was last edited. Note that dragging an image across the gallery may affect the editedon date for a large part of the gallery. + Can be formatted into a user-readable date with the `date` output filter. - - + + #### [[+editedby]] The ID of the MODX User Account that last edited the image record. This can be used with the `userinfo` output filter to show information about that user, for example: - + ```` [[+uploadedby:userinfo=`username`]] ```` @@ -378,7 +554,7 @@ For more information about working with Videos, see the [Videos documentation](. #### [[+service]] -For use in the `&youtubeTpl` or `&vimeoTpl` chunks, this contains either the string `youtube` or `vimeo`. +For use in the `&youtubeTpl` or `&vimeoTpl` chunks, this contains either the string `youtube` or `vimeo`. For more information about working with Videos, see the [Videos documentation](../Video). @@ -388,61 +564,61 @@ The ID of the resource this image was uploaded to. #### [[+resource.KEY_HERE]] -If the `&getResourceFields` property was set as 1, the resource fields are available with the `resource` prefix. For example `[[+resource.pagetitle]]`, `[[+resource.uri]]` or `[[+resource.introtext]]`. +If the `&getResourceFields` property was set as 1, the resource fields are available with the `resource` prefix. For example `[[+resource.pagetitle]]`, `[[+resource.uri]]` or `[[+resource.introtext]]`. The `[[+resource.content]]` placeholder is available if `&getResourceContent` is enabled. -The `[[+resource.properties.NAMESPACE_HERE.KEY_HERE]]` placeholders are available if `&getResourceProperties` is enabled. +The `[[+resource.properties.NAMESPACE_HERE.KEY_HERE]]` placeholders are available if `&getResourceProperties` is enabled. -If a comma separated list of TV names is provided to `&getResourceTVs`, those values are available as `[[+resource.TV_NAME_HERE]]`. +If a comma separated list of TV names is provided to `&getResourceTVs`, those values are available as `[[+resource.TV_NAME_HERE]]`. #### [[+exif.KEY_HERE]] -An array containing the raw EXIF data extracted from the uploaded image. [Learn more about using EXIF in MoreGallery](../Exif). +An array containing the raw EXIF data extracted from the uploaded image. [Learn more about using EXIF in MoreGallery](../Exif). #### [[+exif_dump]] -A readable dump of the EXIF data extracted from the uploaded image. It's best to wrap this in a `pre` tag for better legibility. [Learn more about using EXIF in MoreGallery](../Exif). Added in v1.4. +A readable dump of the EXIF data extracted from the uploaded image. It's best to wrap this in a `pre` tag for better legibility. [Learn more about using EXIF in MoreGallery](../Exif). Added in v1.4. #### [[+exif_json]] -A JSON formatted object of the EXIF data extracted from the uploaded image. [Learn more about using EXIF in MoreGallery](../Exif). Added in v1.4. +A JSON formatted object of the EXIF data extracted from the uploaded image. [Learn more about using EXIF in MoreGallery](../Exif). Added in v1.4. #### [[+iptc.KEY_HERE]] -An array containing the IPTC data extracted from the uploaded image, processed to use normalised names for known elements. [Learn more about using IPTC in MoreGallery](../IPTC). Added in v1.4. +An array containing the IPTC data extracted from the uploaded image, processed to use normalised names for known elements. [Learn more about using IPTC in MoreGallery](../IPTC). Added in v1.4. #### [[+iptc_dump]] -A readable dump of the IPTC data extracted from the uploaded image. It's best to wrap this in a `pre` tag for better legibility. [Learn more about using IPTC in MoreGallery](../IPTC). Added in v1.4. +A readable dump of the IPTC data extracted from the uploaded image. It's best to wrap this in a `pre` tag for better legibility. [Learn more about using IPTC in MoreGallery](../IPTC). Added in v1.4. #### [[+iptc_json]] -A JSON formatted object of the IPTC data extracted from the uploaded image. [Learn more about using IPTC in MoreGallery](../IPTC). Added in v1.4. +A JSON formatted object of the IPTC data extracted from the uploaded image. [Learn more about using IPTC in MoreGallery](../IPTC). Added in v1.4. #### [[+name]] -The name as entered by the user in the backend. +The name as entered by the user in the backend. -**Example**: My Beautiful Image +**Example**: My Beautiful Image #### [[+description]] -The description as entered by the user in the backend. +The description as entered by the user in the backend. #### [[+url]] -The URL as entered by the user in the backend. If a resource ID was entered, this will contain a generated url to the resource. +The URL as entered by the user in the backend. If a resource ID was entered, this will contain a generated url to the resource. #### [[+sortorder]] -The sort order as managed by the user in the backend through drag & drop. +The sort order as managed by the user in the backend through drag & drop. #### [[+view_url]] -An URL to the Gallery resource with the `&iid` URL parameter with the image's ID as value. This is used for image detail pages, instead of linking to the image file directly. +An URL to the Gallery resource with the `&iid` URL parameter with the image's ID as value. This is used for image detail pages, instead of linking to the image file directly. -This is also called the single image view. +This is also called the single image view. #### [[+prev.KEY_HERE]] @@ -450,16 +626,16 @@ An array containing all the same fields above, but then for the image that was b #### [[+next.KEY_HERE]] -An array containing all the same fields above, but then for the image that is next in the result set. For example`[[+next.name]]`. +An array containing all the same fields above, but then for the image that is next in the result set. For example`[[+next.name]]`. #### [[+custom.KEY_HERE]] -An array containing custom field values. [Read more about Custom Fields](../Custom_Fields). Added in v1.4. +An array containing custom field values. [Read more about Custom Fields](../Custom_Fields). Added in v1.4. ## &singleImageTpl Chunk -The singleImageTpl is used when viewing a single image (with the `&iid` URL parameter or the parameter specified in the `&singleImageParam` property, generated by the placeholder. +The singleImageTpl is used when viewing a single image (with the `&iid` URL parameter or the parameter specified in the `&singleImageParam` property, generated by the placeholder. The default chunk used in the singleImageTpl property is the following: @@ -495,6 +671,6 @@ There is no default wrapperTpl chunk. But you might use it like this: ```` -The available placeholders in the wrapperTpl are `[[+output]]`, which contains all the images parsed through imageTpl chunks, and `[[+image_count]]`, which contains the number of matching images. +The available placeholders in the wrapperTpl are `[[+output]]`, which contains all the images parsed through imageTpl chunks, and `[[+image_count]]`, which contains the number of matching images. If you have enabled `&getResourceFields`, the resource data is also available in the wrapperTpl as of v1.4. diff --git a/en/03_MoreGallery/v1.x/Snippets/01_mgGetTags.md b/en/03_MoreGallery/v1.x/03_Snippets/01_mgGetTags.md similarity index 100% rename from en/03_MoreGallery/v1.x/Snippets/01_mgGetTags.md rename to en/03_MoreGallery/v1.x/03_Snippets/01_mgGetTags.md diff --git a/en/03_MoreGallery/v1.x/03_Video.md b/en/03_MoreGallery/v1.x/03_Video.md index 93819008..3c5a84b7 100644 --- a/en/03_MoreGallery/v1.x/03_Video.md +++ b/en/03_MoreGallery/v1.x/03_Video.md @@ -1,13 +1,17 @@ MoreGallery allows embedding videos from YouTube and Vimeo since version 1.5. This made it the first Gallery Extra for MODX that also supports video natively. +> As of version 1.18, you can also embed local videos in MoreGallery. + [TOC] ## Adding videos to a Gallery -To add a video to a Gallery resource, click the _Add Video_ button in the toolbar of the gallery. In the popup, you can paste in the link to a video on YouTube or Vimeo. It will automatically recognise the link, extract its unique video ID, and use that to talk to the YouTube/Vimeo APIs to retrieve a thumbnail. +To add a video from YouTube or Vimeo to a Gallery resource, click the _Add Video_ button in the toolbar of the gallery. In the popup, you can paste in the link to a video on YouTube or Vimeo. It will automatically recognise the link, extract its unique video ID, and use that to talk to the YouTube/Vimeo APIs to retrieve a thumbnail. The name and description of the image will also be pre-filled with information from the video service automatically. Pre-filling the description can be disabled by setting the `moregallery.vimeo_prefill_description` or `moregallery.youtube_prefill_description` system settings to no. +To add a local video, just use the Upload button and select the video from your computer, or use the Import button to select it from the file manager. Note that videos are often larger than PHP is allowed to process, so you may need to increase the memory limit, max_post_size, and upload_max_filesize in your php.ini file. For videos over 100MB, it's better to upload them using FTP instead of the web interface or to use YouTube/Vimeo. + [ ![](https://assets.modmore.com/uploads/2016/07/moregallery_video.gif)](https://assets.modmore.com/uploads/2016/07/moregallery_video.gif) ## Showing videos on your site @@ -24,9 +28,10 @@ When clicking on an image in the default setup, you'll be pointed towards the si [ ![](https://assets.modmore.com/uploads/2016/07/Screen_Shot_2016_07_25_at_22.11.49.png)](https://assets.modmore.com/uploads/2016/07/Screen_Shot_2016_07_25_at_22.11.49.png) + ## Customising the front-end output (listing view) -To change the way videos are shown through the mgGetImages snippet, you can use the `&youtubeTpl` and `&vimeoTpl` snippet properties to provide the name of a new chunk for on listing pages. +To change the way videos are shown through the mgGetImages snippet, you can use the `&youtubeTpl`, `&vimeoTpl`, and `&videoTpl` snippet properties to provide the name of a new chunk for on listing pages. The default for `&youtubeTpl` and `&vimeoTpl` is the following, which will display a static thumbnail image, with a link to the single image view. @@ -60,6 +65,31 @@ For **Vimeo** (`&vimeoTpl`), you could use the following. ```` +The default for `&videoTpl` is the following, which embeds the video directly using the html5 video tag. + +```` html +
  • + +

    + Your browser does not support video. + Download the video file instead. +

    + + +
  • +```` + ## Customising the front-end output (single image view) In the single image view, videos will by default be shown as an embed using the proper YouTube or Vimeo player. @@ -102,4 +132,39 @@ For **Vimeo** (`&singleVimeoTpl`), the default chunk contains:

    ```` +For **local videos** (`&singleVideoTpl`), the default chunk contains: + +```` html +<

    + +

    + Your browser does not support video. + Download the video file instead. +

    + + +

    + +

    + [[+prev.id:notempty=` + « [[+prev.name]] + `]] + [[+name]] + [[+next.id:notempty=` + [[+next.name]] » + `]] +

    +```` + Of course you can customise the embed codes further. The available options for that can be found in the official YouTube Player and Vimeo Player documentation. diff --git a/en/03_MoreGallery/v1.x/04_Custom_Fields.md b/en/03_MoreGallery/v1.x/04_Custom_Fields.md index 59499420..e7183be1 100644 --- a/en/03_MoreGallery/v1.x/04_Custom_Fields.md +++ b/en/03_MoreGallery/v1.x/04_Custom_Fields.md @@ -12,7 +12,7 @@ Note that these custom fields are not built in a way that they are easily search ```` javascript { "story":{ - "label":"Story behind this image", + "label":"How this picture was made", "type":"richtext" }, "copyright":{ diff --git a/en/03_MoreGallery/v1.x/05_Batch_Editing.md b/en/03_MoreGallery/v1.x/05_Batch_Editing.md index f53d0a75..dd27a8e7 100644 --- a/en/03_MoreGallery/v1.x/05_Batch_Editing.md +++ b/en/03_MoreGallery/v1.x/05_Batch_Editing.md @@ -4,7 +4,7 @@ Start by ticking the checkbox shown in the top right of images. This can also be The batch actions toolbar looks like this: -![Batch actions Toolbar](images/bulk-toolbar.jpg) +![Batch actions Toolbar](images/batchedittags.jpg) From left to right, these are the provided functions in the toolbar. @@ -12,6 +12,7 @@ From left to right, these are the provided functions in the toolbar. - Deselect all images (which also hides the bulk toolbar) - Mark all selected images as active/visible - Mark all selected images as inactive/hidden +- Search for tags to add or remove from the selected images (new in v1.8) - Remove all selected images Keyboard users can tab through these options and execute them with `space`. diff --git a/en/03_MoreGallery/v1.x/05_Image_Selector.md b/en/03_MoreGallery/v1.x/05_Image_Selector.md new file mode 100644 index 00000000..1c39d3c6 --- /dev/null +++ b/en/03_MoreGallery/v1.x/05_Image_Selector.md @@ -0,0 +1,38 @@ +As of MoreGallery 1.16 a new Image Selector is included. This feature was sponsored by Catch Media. + +The image selector allows you to choose specific images from one (or multiple) galleries, which you can then output elsewhere. For example to use MoreGallery as some sort of assets library. + +## Availability + +The image selector is available as: + +1. a Template Variable +2. a ContentBlocks input type + +Both work exactly the same, and return a comma-separated list of image IDs as their value. + +> If you did not have ContentBlocks installed when installing MoreGallery 1.16+, you may need to reinstall MoreGallery before the ContentBlocks input type will be available. + +## Configuration (TV) + +Create a new Template Variable and select the `[MoreGallery] Image Select` input type for it. + +You can use its value as `[[*name-of-tv]]`, or `[[+name-of-tv]]` when accessing the resource through pdoResources/getResources. Note you may need to provide `&includeTVs`/`&includeTVList` and `&tvPrefix` in the latter case. + +Where you want the selected image(s) to show up, place the mgGetImages snippet call: + +````html +[[!mgGetImages? + &images=`[[*name-of-tv]]` +]] +```` + +Add additional parameters as needed. + +## Configuration (ContentBlocks) + +Create a new field in Extras > ContentBlocks and choose the `MoreGallery Image Selector` input type for it. + +In the field template you'll already find the mgGetImages snippet call provided the `[[+value]]`. Add additional parameters as needed. + + diff --git a/en/03_MoreGallery/v1.x/09_Pagination.md b/en/03_MoreGallery/v1.x/09_Pagination.md index 94e2f916..329b3d56 100644 --- a/en/03_MoreGallery/v1.x/09_Pagination.md +++ b/en/03_MoreGallery/v1.x/09_Pagination.md @@ -30,7 +30,7 @@ To match it with the Foundation framework, you could add some minimal styling an You can find a lot more information and options specific to getPage in [the getPage documentation](http://rtfm.modx.com/display/ADDON/getPage). -If you get stuck integrating MoreGallery with getPage, feel free to [contact support](https://www.modmore.com/account/support/) for help. +If you get stuck integrating MoreGallery with getPage, feel free to [contact support](https://modmore.com/account/support/) for help. More information about using the mgGetImages snippet and the available properties can be found in the [Snippet Usage](Snippets/mgGetImages) documentation. diff --git a/en/03_MoreGallery/v1.x/10_Example_Galleries/Isotope.md b/en/03_MoreGallery/v1.x/10_Example_Galleries/Isotope.md new file mode 100644 index 00000000..9347d203 --- /dev/null +++ b/en/03_MoreGallery/v1.x/10_Example_Galleries/Isotope.md @@ -0,0 +1,143 @@ +--- +title: Using MoreGallery with Isotope.js +--- + +[Isotope](https://isotope.metafizzy.co/) is a popular JavaScript library for building layouts, with client-side filtering and sort options. + +Setting up a continuous gallery with Isotope and MoreGallery is quite straightforward. + +This example assumes you already have MoreGallery set up with some images; if you haven't yet, see [the getting started guide](../Getting_Started) for where to begin. + +_This tutorial assumes you also have the **pthumb** extra installed. If not, install that from the MODX package manager first._ + +[TOC] + + +## Install Isotope + +First [download Isotope](https://isotope.metafizzy.co/#install). You can download the file manually, install it with npm or bower, or use the provided CDN. + +Do note the Isotope is GPLv3 licensed; there are some restrictions what you can do with the free version. Commercial licenses are quite affordable and help its developer, so maybe consider buying that if you enjoy working with Isotope. + +## Preparing the MoreGallery output + +On your Gallery template (or where-ever you want the gallery to appear), call the [mgGetImages snippet](../Snippets/mgGetImages) like so: + +````html +[[!mgGetImages? + &imageTpl=`gallery-isotope` + &wrapperTpl=`gallery-isotope-wrapper` +]] +```` + +> If you don't have a separate template for your gallery, you can also place the snippet call in the content of the gallery resource. + +> If you use the same template for galleries and non-galleries, you can use the following to only call mgGetImages on a Gallery resource: +> ```html +> [[[[*class_key:eq=`mgResource`:then=`!mgGetImages`:else=`- do nothing`]]? +> &property=`here` +> ]] +> ``` +> This is the so-called mosquito trick, where the inner tag is executed first and constructs a new tag that is then parsed in the next parser cycle. + +Next, create the **gallery-isotope** chunk: + +````html + +```` + +This uses pthumb to generate a 400x400 pixel thumbnail. You can adjust the size as needed for your design. + +And the **gallery-isotope-wrapper** chunk: + +````html +
    + [[+output]] +
    +```` + +If you visit the gallery now, you should see a simple grid of images. They won't be laid out nicely yet - that's what we'll add Isotope for in the next step. + +## Load & initialize Isotope + +Regardless of how you've downloaded Isotope, upload it to a location on your server. + +To initialise the gallery, we'll refer to the [Isotope documentation](https://isotope.metafizzy.co/options.html). In this case we like the [Masonry layout mode](https://isotope.metafizzy.co/layout-modes/masonry.html), but feel free to choose another one. Just check in the documentation as some modes are not included in the original file. + +In your template or footer/scripts chunk, include the Isotope script and initialize it: + +````html + + +```` + +This script will initialize Isotope with the masonry layout mode after all images have loaded. The `columnWidth` is set to `.grid-item` which means Isotope will use the width of your grid items, and `gutter` adds 10px of spacing between items. + +> Note: adjust `[[++assets_url]]lib/isotope.pkgd.min.js` to match the path where you uploaded Isotope on your server. + +If you have a shared template and only want to load Isotope on Gallery resources, wrap the script tags with a condition: + +````html +[[*class_key:eq=`mgResource`:then=` + + +`:else=``]] +```` + +You may want to add some CSS to style your gallery: + +````css +.grid { + max-width: 1200px; + margin: 0 auto; +} + +.grid-item { + width: 30%; + margin-bottom: 10px; +} + +.grid-item img { + display: block; + width: 100%; + height: auto; +} +```` + +For a responsive design, consider using media queries to adjust the grid-item width for different screen sizes. + + diff --git a/en/03_MoreGallery/v1.x/10_Multiple_Galleries.md b/en/03_MoreGallery/v1.x/10_Multiple_Galleries.md index cc847ddf..056c779e 100644 --- a/en/03_MoreGallery/v1.x/10_Multiple_Galleries.md +++ b/en/03_MoreGallery/v1.x/10_Multiple_Galleries.md @@ -46,6 +46,8 @@ If you would like to show more images, adjust the limit property as desired. We' To format the image result we are using the `albumGalleryImage` chunk. +To add a link to the full album from this chunk, you can use `...`. + ## The albumGalleryImage Chunk This chunk is used for each individual image that is returned. Be sure to refer to the [Snippet Usage](Snippets/mgGetImages) document for all available placeholders. @@ -55,4 +57,6 @@ This chunk is used for each individual image that is returned. Be sure to refer [[+resource.pagetitle]]

    [[+name]]

    -```` \ No newline at end of file +```` + +To add a link to the full album page from this chunk, you can use `...`. diff --git a/en/03_MoreGallery/v1.x/Tips_Tricks/01_Responsive_Images.md b/en/03_MoreGallery/v1.x/10_Tips_Tricks/01_Responsive_Images.md similarity index 98% rename from en/03_MoreGallery/v1.x/Tips_Tricks/01_Responsive_Images.md rename to en/03_MoreGallery/v1.x/10_Tips_Tricks/01_Responsive_Images.md index 6071e4c3..2e0337a5 100644 --- a/en/03_MoreGallery/v1.x/Tips_Tricks/01_Responsive_Images.md +++ b/en/03_MoreGallery/v1.x/10_Tips_Tricks/01_Responsive_Images.md @@ -1,6 +1,6 @@ ## Using Picture for Responsive Images -MoreGallery 1.3 added a neat [cropping & resizing feature](https://www.modmore.com/moregallery/documentation/crops/). +MoreGallery 1.3 added a neat [cropping & resizing feature](https://modmore.com/moregallery/documentation/crops/). One of the use cases for that feature is the use of responsive images, where different crops are shown for different browser dimensions. In this document, we'll explain how you can set up your gallery to use `` and `` tags with several different crops. @@ -69,8 +69,8 @@ And add a chunk with the name responsiveImageTpl. Here's an example of what it s - - + + diff --git a/en/03_MoreGallery/v1.x/Tips_Tricks/02_Resource_to_Gallery.md b/en/03_MoreGallery/v1.x/10_Tips_Tricks/02_Resource_to_Gallery.md similarity index 100% rename from en/03_MoreGallery/v1.x/Tips_Tricks/02_Resource_to_Gallery.md rename to en/03_MoreGallery/v1.x/10_Tips_Tricks/02_Resource_to_Gallery.md diff --git a/en/03_MoreGallery/v1.x/99_Data_Sharing.md b/en/03_MoreGallery/v1.x/99_Data_Sharing.md new file mode 100644 index 00000000..2cdce47c --- /dev/null +++ b/en/03_MoreGallery/v1.x/99_Data_Sharing.md @@ -0,0 +1,187 @@ +As of MoreGallery v1.9, your MoreGallery installation will share technical information about your implementation with modmore. This happens during license checks, which happens about once a week. + +To set the consent level, update the **moregallery.data_consent** system setting. During installation or upgrade you can also set the consent level. By default the level is set to 10. + +The data is associated with your license on the modmore server, which means we do have the ability of connecting the collected data to an individual site and the license owner. We may use this data in support or to reach out to individual customers who use certain configurations to request feedback for future functionality. + +We only keep the **latest data** that is shared. When new data is provided, it overwrites the previous data we had stored. To gain insight into long-term trends in MoreGallery usage, we aggregate the data from all sites nightly, and turn that into anonymous insights. + +[TOC] + +## Supported levels + +The default consent level is **10**, which will share basic system settings, gallery and image counts, and your crops and custom field configurations on system and resource level. + +* 0+: consent level and installed version +* 5+: count of gallery resources, values of several settings, system-level crops and custom field configuration +* 7+: count of images by type (image/vimeo/youtube) +* 10+: per-resource overrides of crops and custom field configuration. This only contains the crops/cf config; not other resource information +* 12+: source_relative_url system setting +* 15+: per-resource override of source relative url + +## Seeing what data you're sharing + +To see the exact data that is shared from your site, call the `mgGetImages` snippet with the `&showCollectedData` property: + +```html +[[!mgGetImages? &showCollectedData=`1`]] +``` + +That will dump the exact data to screen for you to inspect. + +## Example data + +### Level 0 + +```json +{ + "level": 0, + "version": "1.9.0-pl" +} +``` + +### Level 5 + +``` json +{ + "level": 5, + "version": "1.9.0-pl", + "resources": 5, + "settings": { + "image_id_in_name": "prefix", + "content_position": "below", + "use_rte_for_images": "1", + "allowed_extensions_per_source": "" + }, + "crops": [], + "custom_fields": [ + "{ \"stories\":{ \"label\":\"Stories behind this image\", \"type\":\"richtext\" }, \"copyright\":{ \"label\":\"Copyright\" }, \"class\":{ \"label\":\"Extra Class\", \"type\":\"select\", \"options\":[{ \"value\":\"\", \"label\":\"None\" },{ \"value\":\"boxed\", \"label\":\"Boxed thumbnail\" }] }}" + ] +} +``` + +### Level 7 + +```json +{ + "level": 7, + "version": "1.9.0-pl", + "resources": 5, + "settings": { + "image_id_in_name": "prefix", + "content_position": "below", + "use_rte_for_images": "1", + "allowed_extensions_per_source": "" + }, + "crops": [], + "custom_fields": [ + "{ \"stories\":{ \"label\":\"Stories behind this image\", \"type\":\"richtext\" }, \"copyright\":{ \"label\":\"Copyright\" }, \"class\":{ \"label\":\"Extra Class\", \"type\":\"select\", \"options\":[{ \"value\":\"\", \"label\":\"None\" },{ \"value\":\"boxed\", \"label\":\"Boxed thumbnail\" }] }}" + ], + "types": { + "mgImage": 44, + "mgVimeoVideo": 7, + "mgYouTubeVideo": 10 + } +} +``` + +### Level 10 + +```json +{ + "level": 10, + "version": "1.9.0-pl", + "resources": 5, + "settings": { + "image_id_in_name": "prefix", + "content_position": "below", + "use_rte_for_images": "1", + "allowed_extensions_per_source": "" + }, + "crops": [ + "small:width=200,height=400", + "desktop:default_aspect=1.75,width=600|mobile:default_aspect=1.75,width=200", + "foo", + "small:width=200,height=200,aspect=1|medium:width=500,aspect=0.7|large:height=750" + ], + "custom_fields": [ + "{ \"stories\":{ \"label\":\"Stories behind this image\", \"type\":\"richtext\" }, \"copyright\":{ \"label\":\"Copyright\" }, \"class\":{ \"label\":\"Extra Class\", \"type\":\"select\", \"options\":[{ \"value\":\"\", \"label\":\"None\" },{ \"value\":\"boxed\", \"label\":\"Boxed thumbnail\" }] }}", + "{\"class\":{\"label\":\"Slide Type\",\"type\":\"select\",\"options\":[{\"value\":\"\",\"label\":\"All Devices\"},{\"value\":\"desktop-only\",\"label\":\"Desktop Only\"},{\"value\":\"mobile-only\",\"label\":\"Mobile Only\"},{\"value\":\"text-slide\",\"label\":\"Text Slide\"}]}}" + ], + "types": { + "mgImage": 44, + "mgVimeoVideo": 7, + "mgYouTubeVideo": 10 + } +} +``` + +### Level 12 + +``` json +{ + "level": 12, + "version": "1.9.0-pl", + "resources": 5, + "settings": { + "image_id_in_name": "prefix", + "content_position": "below", + "use_rte_for_images": "1", + "allowed_extensions_per_source": "" + }, + "crops": [ + "small:width=200,height=400", + "desktop:default_aspect=1.75,width=600|mobile:default_aspect=1.75,width=200", + "foo", + "small:width=200,height=200,aspect=1|medium:width=500,aspect=0.7|large:height=750" + ], + "custom_fields": [ + "{ \"stories\":{ \"label\":\"Stories behind this image\", \"type\":\"richtext\" }, \"copyright\":{ \"label\":\"Copyright\" }, \"class\":{ \"label\":\"Extra Class\", \"type\":\"select\", \"options\":[{ \"value\":\"\", \"label\":\"None\" },{ \"value\":\"boxed\", \"label\":\"Boxed thumbnail\" }] }}", + "{\"class\":{\"label\":\"Slide Type\",\"type\":\"select\",\"options\":[{\"value\":\"\",\"label\":\"All Devices\"},{\"value\":\"desktop-only\",\"label\":\"Desktop Only\"},{\"value\":\"mobile-only\",\"label\":\"Mobile Only\"},{\"value\":\"text-slide\",\"label\":\"Text Slide\"}]}}" + ], + "types": { + "mgImage": 44, + "mgVimeoVideo": 7, + "mgYouTubeVideo": 10 + }, + "source_relative_url": [ + "assets\/galleries\/" + ] +} +``` + +### Level 15 + +``` json +{ + "level": 15, + "version": "1.9.0-pl", + "resources": 5, + "settings": { + "image_id_in_name": "prefix", + "content_position": "below", + "use_rte_for_images": "1", + "allowed_extensions_per_source": "" + }, + "crops": [ + "small:width=200,height=400", + "desktop:default_aspect=1.75,width=600|mobile:default_aspect=1.75,width=200", + "foo", + "small:width=200,height=200,aspect=1|medium:width=500,aspect=0.7|large:height=750" + ], + "custom_fields": [ + "{ \"stories\":{ \"label\":\"Stories behind this image\", \"type\":\"richtext\" }, \"copyright\":{ \"label\":\"Copyright\" }, \"class\":{ \"label\":\"Extra Class\", \"type\":\"select\", \"options\":[{ \"value\":\"\", \"label\":\"None\" },{ \"value\":\"boxed\", \"label\":\"Boxed thumbnail\" }] }}", + "{\"class\":{\"label\":\"Slide Type\",\"type\":\"select\",\"options\":[{\"value\":\"\",\"label\":\"All Devices\"},{\"value\":\"desktop-only\",\"label\":\"Desktop Only\"},{\"value\":\"mobile-only\",\"label\":\"Mobile Only\"},{\"value\":\"text-slide\",\"label\":\"Text Slide\"}]}}" + ], + "types": { + "mgImage": 44, + "mgVimeoVideo": 7, + "mgYouTubeVideo": 10 + }, + "source_relative_url": [ + "assets\/galleries\/", + "testgalleries\/local\/" + ] +} +``` + diff --git a/en/03_MoreGallery/v1.x/images/batchedittags.jpg b/en/03_MoreGallery/v1.x/images/batchedittags.jpg new file mode 100644 index 00000000..8fd4a849 Binary files /dev/null and b/en/03_MoreGallery/v1.x/images/batchedittags.jpg differ diff --git a/en/03_MoreGallery/v1.x/images/bulk-toolbar.jpg b/en/03_MoreGallery/v1.x/images/bulk-toolbar.jpg deleted file mode 100644 index b2bfe3bd..00000000 Binary files a/en/03_MoreGallery/v1.x/images/bulk-toolbar.jpg and /dev/null differ diff --git a/en/03_MoreGallery/v1.x/index.md b/en/03_MoreGallery/v1.x/index.md index 5ec5938b..7397ae4c 100644 --- a/en/03_MoreGallery/v1.x/index.md +++ b/en/03_MoreGallery/v1.x/index.md @@ -1,13 +1,13 @@ --- -title: MoreGallery -description: Documentation for MoreGallery, a premium extra from modmore for MODX. +title: MoreGallery 1.x +description: Documentation for MoreGallery, a premium extra from modmore for MODX. --- -[MoreGallery](https://www.modmore.com/moregallery/) is an intuitive and fully featured image gallery for MODX with tags, cropping, custom fields and video. +[MoreGallery](https://modmore.com/moregallery/) is an intuitive and fully featured image gallery for MODX with tags, cropping, custom fields and video. # Recommended Reading - [Getting Started](Getting_Started) - [Configuration](Configuration) - [mgGetImages Snippet](Snippets/mgGetImages) -- [mgGetTags Snippet](Snippets/mgGetTags) \ No newline at end of file +- [mgGetTags Snippet](Snippets/mgGetTags) diff --git a/en/04_Redactor/01_v2.x/index.md b/en/04_Redactor/01_v2.x/index.md deleted file mode 100644 index 2804f94d..00000000 --- a/en/04_Redactor/01_v2.x/index.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Redactor -description: Documentation for Redactor (version 2), a premium extra from modmore for MODX. ---- - -[Redactor](https://www.modmore.com/redactor/) is a beautiful, user friendly, and configurable rich text editor for MODX with powerful media management. - -# Recommended Reading - -- [Configuration](Configure_Redactor) -- [Managing Media](Managing_Media) diff --git a/en/04_Redactor/01_v3.x/01_Quickstart.md b/en/04_Redactor/01_v3.x/01_Quickstart.md new file mode 100644 index 00000000..96fa30c2 --- /dev/null +++ b/en/04_Redactor/01_v3.x/01_Quickstart.md @@ -0,0 +1,86 @@ +--- +title: Quickstart Guide +--- + +Welcome to Redactor 3. We hope this will be your favorite editor for MODX, if it isn't already. + +The focus in Redactor is on a simple, clean, and user friendly rich text editor. It's not a page builder (though it integrates extremely well with [ContentBlocks](https://modmore.com/contentblocks/)!), but does output clean markup and various types of media. + +Let's take a quick tour of Redactor! + +[TOC] + +## Managing Configuration + +After installing Redactor, you'll find a new page in the manager dedicated to its configuration in the Extras menu. + +![Redactor Configuration under Extras in the MODX 2.x manager](images/menu-entry.jpg) + +In this manager page, you'll manage what we call **Configuration Sets**. Each set is one unique implementation of Redactor, which can be enabled system-wide, in specific contexts, for specific templates, to the custom template variable input type or resource introtext, or ContentBlocks input types. + +For each way you can use Redactor, check the [Usage documentation](Usage). + +### Default configuration sets + +By default you'll find 2 configuration sets we've prepared for you: Standard and Minimal. + +- Standard is a pretty, erm, _standard_ configuration of Redactor. It covers the most commonly used features and toolbar buttons that works well. It doesn't enable all features, mind you, but a good portion of them. +- Minimal is a much more slimmed down implementation. It's toolbar is limited to basic text functionality and inserting images. + +Here's a quick side-by-side view of the Minimal vs the Standard set. + +![Minimal configuration set (on the left) vs the Standard configuration set (on the right)](images/min-vs-standard.png) + +You can edit these sets as you'd like - they **will not** be overwritten on upgrade. + +> Tip: when changing a configuration, use the ctrl/cmd+s shortcut to quickly save the configuration. + +### Exports & Imports + +When you've spent some time creating a configuration set that you like, you can re-use it on different sites. + +- In the set configuration view, click on Export in the top right menu to export the set you're currently editing. +- In the list of sets, right click on a specific set and choose Export to export a specific set. +- In the list of sets, click the Export button on the top right of the grid to export all sets. + +The generated XML file can be imported on any Redactor 3 installation by clicking the Import button in the sets overview and uploading the file. + +When importing you can choose 3 different import modes. + +- With the **Insert** mode, the ID in the export is ignored and all sets in the XML file are created alongside any existing sets. +- With the **Overwrite** mode, any existing sets with the same ID of a set in the XML file will be overwritten. Existing sets that don't have a matching set in the export, are left as they were. +- With the **Replace** mode, all existing sets are first removed, before the sets in the XML file are created. + +The exports do not contain any references to where you've enabled a certain set. + +To quickly set an imported configuration set as default, you can right click it in the list of sets and choose **Set as system default**. For other ways to assign configuration sets to be used, [see the usage section](Usage). That includes per-template and per-context options, and others. + +## Using the Redactor Template Variable + +Redactor will automatically enhance standard MODX richtext template variables with the _default_ configuration set. This means that the content and richtext fields use the same configuration. + +If you'd like to use a different configuration for a template variable, you can use the provided Redactor template variable type. [Learn more about the Redactor template variable »](Usage/Template_Variables) + +## Using Redactor with ContentBlocks + +Also use [ContentBlocks](https://modmore.com/contentblocks/)? Then you can use the [provided Redactor input type](Usage/ContentBlocks) to use a specific configuration set for rich text fields for more control. + +## Themes + +Redactor 3 ships with a selection of different editor themes, including one that looks like Redactor 2 to help ease the transition and a dark mode. [Choose the one you like most](Themes), or [build your own](Themes/Custom). + +## Shortcuts & Shortcodes + +With the [available shortcuts](Shortcuts) you can execute some common commands without needing to leave the keyboard. + +With the [shortcodes](Shortcodes) you can start typing certain codes at the start of a new line to apply standard formatting. + +## More features + +It's encouraged to start editing your configuration set to learn about all the features Redactor uses. Each option has a description in the editing view to help you understand what it does. + +For the more powerful functionality, we have [extended documentation](Features). The configuration set view will also link to documentation where applicable. + +## Restrict access to the configurator + +To restrict access to the configurator, you can use the [provided access permissions](Permissions). diff --git a/en/04_Redactor/01_v3.x/02_Configuration_Sets.md b/en/04_Redactor/01_v3.x/02_Configuration_Sets.md new file mode 100644 index 00000000..c13cbe08 --- /dev/null +++ b/en/04_Redactor/01_v3.x/02_Configuration_Sets.md @@ -0,0 +1,59 @@ +Configuration sets are how you manage the configuration for Redactor. They are found in **Extras > Redactor Configuration** and will show you a live preview of the chosen configuration. + +[TOC] + +## Available options + +Each set contains all the different options that are available, with a detailed description. + +For some more complex functionality with more advanced options, additional documentation is available in the [Features section](Features/index). + +### Default Configuration Sets + +When you first install Redactor 3, we install two default configuration sets for you. + +- One, called "Standard", is a pretty basic implementation that should work well for most users. It does not enable all options, but what the most common ones. +- Second, called "Minimal", is a much more minimal configuration. + +You can edit these default sets as you see fit; they will not be overwritten on upgrade. + +If you wish to restore the default sets, you need to first remove all configuration sets. Then go to Extras > Installer and choose _Reinstall_ for Redactor. The default sets will be created again. + +## Exports & Import + +From the configuration sets overview, you can export and import sets. + +If you click the Export button at the top right of the grid, that will download an XML export of all the configured sets. Alternatively you can right click on a specific set and click Export in the context menu to only export a single set. + +To import sets, click the Import button in the top right of the grid. + +Exports are not bound to a specific installation, so you can use exports to quickly start new sites with the same configuration. Usage configuration is not included in the export. + +When contacting support about editor issues, please also include an export of the configuration set you use. + +## Duplicate + +To duplicate sets, right click the set and choose Duplicate. Enter a new name and description and save. + +## Assigning usage + +Once you've created sets, you can assign sets to be used globally, for specific contexts, and for specific template variables. + +To quickly assign a configuration set as the system default, you can right click a set in the grid and choose "Set as system default". This requires permission to edit settings. + +To learn how to configure what set to use in different places, see: + +- [Resource content](Usage/Content) +- [Template-specific overrides for the content](Usage/Template) +- [Resource introtext](Usage/Introtext) +- [Template variables](Usage/Template_Variables) +- [ContentBlocks fields](Usage/ContentBlocks) +- [Third-party extra](Usage/Third_Party_Extras) + +## Custom Preview Contents + +By default the configurator shows some dummy text. Some lorum ipsum, an image, some links and various formatting. + +If you'd rather use custom content for the preview (for example to showcase custom styles or other elements), you can do so by creating a chunk. + +Create a chunk named `redactor_configurator_preview`, and provide your content. Refresh the configurator. diff --git a/en/04_Redactor/01_v3.x/03_Usage/Content.md b/en/04_Redactor/01_v3.x/03_Usage/Content.md new file mode 100644 index 00000000..2a81fef2 --- /dev/null +++ b/en/04_Redactor/01_v3.x/03_Usage/Content.md @@ -0,0 +1,22 @@ +Once installed, Redactor automatically enhances the standard content field with the rich text editor. + +To change the configuration set that is used for the content, go to the system settings and add the configuration set ID to the `redactor.configuration_set` setting. + +[TOC] + +## Context overrides + +You can set different configuration sets per context. To do this, create a context setting with key `redactor.configuration_set` and provide it the ID of the configuration set you want to use in that context. + +## Template overrides + +To use a different configuration set by template, see [template overrides](Template). + +## Editor not showing + +Redactor uses a couple of factors to determine if the editor should be shown. If you're not seeing the editor, or if you want to prevent the editor in certain cases, check these options. + +- Make sure the `use_editor` system setting is enabled. +- Make sure the `which_editor` system setting is enabled. (If you want to disable editors globally, or use a different editor for the content, you can use the [Redactor template variable](Template_Variables) which will work regardless of this setting) +- On specific resources, make sure `Rich text` is checked on the resource settings tab. + \ No newline at end of file diff --git a/en/04_Redactor/01_v3.x/03_Usage/ContentBlocks.md b/en/04_Redactor/01_v3.x/03_Usage/ContentBlocks.md new file mode 100644 index 00000000..48840d21 --- /dev/null +++ b/en/04_Redactor/01_v3.x/03_Usage/ContentBlocks.md @@ -0,0 +1,11 @@ +Redactor also ships with a custom input type for use with [ContentBlocks](https://modmore.com/contentblocks/). + +Similar to the [custom template variable type](Template_Variables), this allows you to set different configuration sets for different fields. + +## Creating a Field + +With Redactor and ContentBlocks installed, go to Extras > ContentBlocks and create a new field. For the Input Type, choose `Rich Text - Redactor`, located at the bottom of the list. + +![Selecting the Redactor input type for ContentBlocks](../images/contentblocks-input.jpg) + +On the **Properties** tab you can select the configuration set to use. diff --git a/en/04_Redactor/01_v3.x/03_Usage/Fred.md b/en/04_Redactor/01_v3.x/03_Usage/Fred.md new file mode 100644 index 00000000..42fede87 --- /dev/null +++ b/en/04_Redactor/01_v3.x/03_Usage/Fred.md @@ -0,0 +1,93 @@ +[Fred](http://modx.com/extras/package/fred) is a front-end visual page builder. While we obviously prefer [ContentBlocks](https://modmore.com/contentblocks/), Redactor 3 includes **experimental** support for Fred. + +Experimental means that it's functional, but that we may decide to drop support in the future. Due to our limited first-hand experience with Fred, we may not be able of reaching the same level of support as we can for our ContentBlocks and standard MODX integrations. + +[TOC] + +## Getting Started + +If you already have a functional Fred set-up with support for the standard TinyMCE rich text editor, you can easily switch to Redactor. Skip ahead to _Enabling Redactor_. + +### Prepare a rich text enabled element + +In the Fred manager component, create/update an element. For its markup, you will need to define: + +- A div element for the content +- `data-fred-name="text"` (or a different name) to make Fred save the value +- `data-fred-rte="true"` to enable rich text support +- Optionally, `data-fred-rte-config="redactor_text" (or a different name) to set the configuration. See _Customising Redactor_, below. + +For example, your element markup could look like this: + +``` html +
    +
    +
    +

    Learn more about this awesome feature!

    +
    +

    There's so much you can do here. Make it pop!

    +
    +
    +
    +
    +``` + +### Enabling Redactor + +Once you have a rich text element, you can start using Redactor for it. + +If you haven't installed Redactor 3 yet, you'll need to do that first. + +In the manager, under System > System Settings, search for the `fred.rte` system setting, and type in `Redactor`. + +If you now visit a Fred-enabled page and add your rich text element to it, you should see Redactor is initialised. + +## Customising Redactor + +Redactor uses [Configuration Sets](../Configuration_Sets) to manage its different configuration. We recommend creating a unique set for Fred as you'll likely want slightly different configuration for Fred then you would for other things in the manager. + +### Create a configuration set + +Start by creating a new configuration set (or duplicating one you like) and opening it to change its settings. + +- We recommend enabling **Air Mode** (in the Toolbar tab), which will hide the toolbar until you select some text. For a visual editor like Fred, that's probably ideal. Redactor will work in Fred without air mode, but the toolbar will be visible at all times. +- You can [choose a theme you like](../Themes), but on light sites we recommend to use the `dark` theme, and on dark sites we recommend using the `default` (or `redactor2`) theme. That ensures the toolbar properly stands out. Note that within the context of Fred, themes only affect the toolbar and not the content. + +When you have a configuration set you like, save it, and move on to the next section where we tell Fred which one to use. + +### Choosing a configuration set + +Without any Fred-specific configuration, the default configuration set will be used. This supports context overrides ([learn more](Content)) as well as [template-based configuration sets](Template). + +If you're happy with that, you're all set! + +If you'd rather use specific sets in Fred, perhaps even a different configuration set for a different type of element, you can do that with a [Fred RTE Config](https://modxcms.github.io/fred/themer/cmp/rte_configs/). + +In the Fred component, go to RTE Configs and create a new RTE config. In our markup example earlier we called it `redactor_text`, but you can change the name to something else. + +For the content, provide a JSON object with a key `configuration_set` and the ID of the configuration set you want to use. + +For example: + +```json +{ + "configuration_set": 2 +} +``` + +At this time, no other options can be provided in a Fred RTE Config. + +Redactor will now use the provided configuration set for the element. RTE Configs override other ways of setting the configuration set to use. + +## Limitations + +Only the "Simple" media browser is supported for inserting existing files and images. The standard MODX browser is not available in Fred. + +Redactor does not currently integrate with Fred's elFinder, but we may add that in a future release given enough people use Redactor with Fred. Be sure to let us know if you're using Fred and would like us to support the additional finder. + +Unlike TVs and ContentBlocks fields, Fred elements are not shown in the usage column for configuration sets. + +## Fred Tips + +- [Shortcodes](../Shortcodes) are a great companion for a rich text editor in Fred. Just type `h2.` to switch to a header level 2. +- Create different configurations for different elements. A primary blog content section could be configured to allow more toolbar features than a piece of hero text. diff --git a/en/04_Redactor/01_v3.x/03_Usage/Introtext.md b/en/04_Redactor/01_v3.x/03_Usage/Introtext.md new file mode 100644 index 00000000..9eecb6b6 --- /dev/null +++ b/en/04_Redactor/01_v3.x/03_Usage/Introtext.md @@ -0,0 +1,9 @@ +If you want to add some rich text into the resource introtext, then you can use Redactor for that. + +This is disabled by default. To enable it, go to System > System Settings and find the `redactor.introtext` system setting. Enable it. + +To change what configuration set is used for the introtext, change the `redactor.introtext.configuration_set` system setting. Enter the ID of a valid configuration set, which you can find in Extras > Redactor Configuration. + +A minimal configuration set, or one with Air Mode enabled, works great with the introtext. + +![Minimal configuration set shown on the resource introtext](../images/introtext.jpg) diff --git a/en/04_Redactor/01_v3.x/03_Usage/MIGX.md b/en/04_Redactor/01_v3.x/03_Usage/MIGX.md new file mode 100644 index 00000000..8c8f6e8e --- /dev/null +++ b/en/04_Redactor/01_v3.x/03_Usage/MIGX.md @@ -0,0 +1,33 @@ +Looking to use a rich text editor in your MIGX TV? Look no further than Redactor 3. + +## Standard configuration set + +[By following the MIGX Backend-Usage tutorial](https://docs.modx.com/current/en/extras/migx/migx.backend-usage), you'll get the default Redactor configuration set inside your form. This is because in the Form Tabs, you've defined `"inputTVtype": "richtext"` - which grabs the default editor in the default configuration. + +The inputTVtype `migxredactor` (from v2, shipped with MIGX) also works. + +## MIGX-specific configuration set + +To use a configuration set specific to the MIGX instance, you can use the provided `migxredactor3` (note: the one with the 3 suffix!) input TV type. That accepts a `configs` option to provide the ID of the configuration set to use. + +In your form tabs, add two things: + +- `"inputTVtype": "migxredactor3"` +- `"configs": id-of-configuration-set` + +For example, to use configuration set #12 on a description field, your MIGX form tabs configuration would look something like this: + +``` js +[{ + "caption": "Info", + "fields": [{ + "field": "title", + "caption": "Title" + },{ + "field": "description", + "caption": "Description", + "inputTVtype": "migxredactor3", + "configs": 12 + }] +}] +``` diff --git a/en/04_Redactor/01_v3.x/03_Usage/Template.md b/en/04_Redactor/01_v3.x/03_Usage/Template.md new file mode 100644 index 00000000..560b8910 --- /dev/null +++ b/en/04_Redactor/01_v3.x/03_Usage/Template.md @@ -0,0 +1,19 @@ +Redactor defaults to the configuration set configured through the `redactor.configuration_set` System Setting, which can be overridden with Context Settings with the same key. + +There are also separate options to choose the configuration set for [Template Variables](Template_Variables), [ContentBlocks](ContentBlocks) and the [introtext field](Introtext). + +If you want to get more granular in defining the configuration set **for the content field**, you can configure a per-template configuration set. + +## How-to + +To set up a different set for a template, edit the template and go to its Properties tab. + +![Showing how to add the property to the template](../images/template-properties.jpg) + +1. First, unlock the default properties. + +2. Create a new property with the key `redactor.configuration_set` and the ID of the configuration set you want to use as value. + +3. Save the property set, and save the template. + +When set up correctly, you should see the template listed in the Redactor Configuration grid, and editing a resource with that template will use the chosen configuration. diff --git a/en/04_Redactor/01_v3.x/03_Usage/Template_Variables.md b/en/04_Redactor/01_v3.x/03_Usage/Template_Variables.md new file mode 100644 index 00000000..2cc85d47 --- /dev/null +++ b/en/04_Redactor/01_v3.x/03_Usage/Template_Variables.md @@ -0,0 +1,19 @@ +Redactor automatically enhances standard richtext TVs, using the default configuration set. + +To use a different configuration set for a template variable, use the provided Redactor template variable input type. + +[TOC] + +## Create the configuration set + +First create your configuration in Extras > Redactor. + +## Create the template variable + +Create a new template variable through the Elements tab. On the _Input Options_ tab, set the _Input Type_ to `redactor` (at the bottom of the list). + +Below, select the desired configuration set to use. + +Make sure to assign the template access and you're good to go! + +Alternatively, you can also change the input type for an existing `richtext` template variable to `redactor`. This will preserve your content. diff --git a/en/04_Redactor/01_v3.x/03_Usage/Third_Party_Extras.md b/en/04_Redactor/01_v3.x/03_Usage/Third_Party_Extras.md new file mode 100644 index 00000000..dee96144 --- /dev/null +++ b/en/04_Redactor/01_v3.x/03_Usage/Third_Party_Extras.md @@ -0,0 +1,156 @@ +Third-party extras can also use Redactor. + +Third party extras can support a generic rich text editor implementation, which works for Redactor, TinyMCE and CKEditor from the same code, or they can use a Redactor-specific implementation that allows defining the configuration set to use. + +Most extras use the generic approach, which will cause it to use the system default configuration set. + +[TOC] + +## Supported third party extras + +- FaqMan +- MoreGallery +- ContentBlocks (also see [the custom Redactor input type](ContentBlocks)) +- Agenda +- Articles +- mxCalendar + +Please note that this list is incomplete. + +## Implementing rich text editing + +This section is only for developers looking to implement Redactor and/or other editors into their extras. + +### Step 1. Invoke the OnRichTextEditorInit event + +The OnRichTextEditorInit event calls the Redactor plugin which prepares the HTML and loads the necessary assets. + +The return value from the invokeEvent method needs to be inserted into your page; this contains instantiation logic for Redactor. + +The easiest way to do that is in your **controller,** set the placeholder there, and make sure it is inserted into your template. + +Add this method inside your Controller: + +```` php +modx->getOption('use_editor'); + $whichEditor = $this->modx->getOption('which_editor'); + if ($useEditor && !empty($whichEditor)) + { + // invoke the OnRichTextEditorInit event + $onRichTextEditorInit = $this->modx->invokeEvent('OnRichTextEditorInit',array( + 'editor' => $whichEditor, // Not necessary for Redactor + 'elements' => array('foo'), // Not necessary for Redactor + )); + if (is_array($onRichTextEditorInit)) + { + $onRichTextEditorInit = implode('', $onRichTextEditorInit); + } + $this->setPlaceholder('onRichTextEditorInit', $onRichTextEditorInit); + } + } + + public function process() + { + // Call your method to grab the editor code + $this->loadRichTextEditor(); + } +} + +```` + +Make sure to call the loadRichTextEditor method from your process() method! + +Next, you need to make sure that the output of the event (`$onRichTextEditorInit`) is inserted into the page. In the code example above we're using the `setPlaceholder` method of the manager controller to store a placeholder. We'll need to reference that placeholder in our template, which uses Smarty. + +Here's an example template file for the Controller: + +```` html +
    +{$onRichTextEditorInit} +```` + +### Call MODx.loadRTE(elements) or MODx.loadRedactorConfigurationSet(elements, set) + +The second step is to call the javascript method that initiates the editor. For this, you have two options. + +1. Use `MODx.loadRTE(elements)` for the generic RTE integration, which will also work for other rich text editors. +2. Use `MODx.loadRedactorConfigurationSet(elements, set)` for the Redactor-specific integration, which allows you to pass the ID of a configuration set to use. + +In both cases, `elements` is a comma-separated list of textarea IDs (without hash `#`) that should be enhanced. + +#### Basic example + +For example: + +````javascript +if (MODx.loadRTE) { + // Will transform the textarea with ID "description" to a RTE + MODx.loadRTE('description'); +} +```` + +You can also choose to use the Redactor approach when available, and fallback to the generic one when it is not. + +```` javascript +if (MODx.loadRTE) { + var initialise = MODx.loadRedactorConfigurationSet || MODx.loadRTE, + redactorSet = 4; + // Will transform the textarea with ID "description" to a RTE + initialise('description', redactorSet); +} +```` + +It is theoretically possible for other editors to expect a different second parameter for MODx.loadRTE, so make sure to test this with the editors you wish to support. + +#### Window example + +If you're loading the editor in an ExtJS modal window, you can hook into the "show" or "activate" events for the Window to call MODx.loadRTE. Have a look at the [faqMan source](https://github.com/josht/faqMan/blob/develop/assets/components/faqman/js/mgr/widgets/items.grid.js#L271) to see this integration in action and context. Here's an example: + +```` javascript +this.on('activate', function() { + if (MODx.loadRTE) { + MODx.loadRTE('id-of-the-field-to-be-richtext'); + } +}); +```` + +Also add this option to your MODx.Window to prevent Redactor from double initialization. + +```javascript +closeAction: 'close' +``` + +### Allow customer to select a configuration set + +If you went with the Redactor-specific (or hybrid) approach, you'll want to offer your user the ability to select a configuration set. You can make this available as a system setting for example. + +To incorporate the selection into an ExtJS based component, you can use the provided combo box. + +To load it, add the following to a controller or plugin: + +```php +getOption('redactor.assets_url', null, MODX_ASSETS_URL . 'components/redactor/'); +$modx->controller->addJavascript($assetsUrl . 'configuration/widgets/combo.configsets.js'); + +$connectorUrl = $assetsUrl . 'connector.php'; +$modx->controller->addHTML(<< +if (!window.RedactorConfiguration) { + window.RedactorConfiguration = { + config: { + connectorUrl: '{$connectorUrl}' + } + } +} + +HTML +); +``` + +Now you can use the `redactor-configsets` xtype. diff --git a/en/04_Redactor/01_v3.x/03_Usage/index.md b/en/04_Redactor/01_v3.x/03_Usage/index.md new file mode 100644 index 00000000..f12cec7f --- /dev/null +++ b/en/04_Redactor/01_v3.x/03_Usage/index.md @@ -0,0 +1,11 @@ +Redactor can be used in different places in different ways. These different use cases can be configured in different ways, too. + +- [The resource content and standard template variables](Content) +- [With the custom Redactor template variable type](Template_Variables) +- [On the resource introtext](Introtext) +- [Different configurations per template](Template) +- [As custom ContentBlocks rich text field](ContentBlocks) +- [As part of MIGX](MIGX) + +It's also possible to use Redactor with [third party extras](Third_Party_Extras). + diff --git a/en/04_Redactor/01_v3.x/Features/Autoparse.md b/en/04_Redactor/01_v3.x/Features/Autoparse.md new file mode 100644 index 00000000..8503cd49 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Autoparse.md @@ -0,0 +1,18 @@ +With the autoparse options, enabled in the Links section of the configurator, you can simply paste certain types of links and they will be automatically processed. + +[TOC] + +## Autoparse images + +With images, you can paste the link to an image and it will be inserted. + +## Autoparse videos + +Pasting a link to a YouTube or Vimeo video page will automatically embed the video. + +As an alternative to providing the link, you can also use the Video toolbar button to provide an embed code instead. + +## Autoparse links + +When pasting in a URL, it will be turned into a proper link. The link text is the URL. To control the length of the link text, configure the _Link text length_ setting. + diff --git a/en/04_Redactor/01_v3.x/Features/Clips.md b/en/04_Redactor/01_v3.x/Features/Clips.md new file mode 100644 index 00000000..896ee36b --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Clips.md @@ -0,0 +1,22 @@ +Clips are pre-set elements or special characters available from a simple interface. They are configured in **Text Utilities > Clips** as a JSON array of arrays. + +For example: + +``` JSON +[ + ["Lorem ipsum...", "Lorem..."], + ["Red label", "Label"] +] +``` + +Be sure to use **"double quotes"** or it will not be considered valid JSON. + +## Special Characters + +If you want to add the ability to easily insert special characters, you can also add `specialchars` to your toolbar instead of using Clips. That automatically adds a special button for common special characters to insert. + +## Clips from 2.x + +Redactor 2.x also had Clips, but with a different structure. That structure is also recognised in 3.x and will be automatically converted on save. + +[You can find a whole bunch of example configurations in the 2.x Clips documentation](../../v2.x/Clips), including currency selectors and other special characters. diff --git a/en/04_Redactor/01_v3.x/Features/Custom_CSS.md b/en/04_Redactor/01_v3.x/Features/Custom_CSS.md new file mode 100644 index 00000000..0d706c89 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Custom_CSS.md @@ -0,0 +1,20 @@ +In certain cases you'll want to load a custom CSS stylesheet for use in the editor. For example when you provide [custom formatting options](Custom_Formatting), [image styles](Image_Styles), [link styles](Link_Styles) or a [completely custom theme](../Themes/Custom). + +To do this, create a CSS file in your preferred location (such as `/assets/template/editor.css`) and add a fully qualified link to the `redactor.css` system setting. + +If needed, you can add multiple CSS files to the `redactor.css` system setting; simply separate them with a comma. + +**Scope all your custom styles to `.redactor-box` to avoid causing side-effects in the manager.** + +For example: + +``` css +.redactor-box h3.my_special_class { + color: #ff9900; + font-weight: bolder; +} +``` + +Some HTML structures have a slightly different representation in the editor than their final output and the source view. It can be useful to use the browser developer tools to inspect the way the content is rendered in such cases. + +If you have a common set of styles that you use in the editor, please [share it with others on the forum](https://forum.modmore.com/c/redactor) \ No newline at end of file diff --git a/en/04_Redactor/01_v3.x/Features/Custom_Formatting.md b/en/04_Redactor/01_v3.x/Features/Custom_Formatting.md new file mode 100644 index 00000000..ac516a14 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Custom_Formatting.md @@ -0,0 +1,90 @@ +Custom formatting options are used to add custom styles to the content. They can be provided classes, styles, and attributes. + +Custom formatting options are added into the regular formatting dropdown, and configured as JSON in your configuration set under Formatting. + +[TOC] + +## Structure + +Custom formatting is defined as a nested JSON object. Make sure to use **double quotes** for values and keys. + +The top-level keys are the names, which correspond to a class that will be added to the toolbar dropdown in the editor in the format `.redactor-dropdown-format .redactor-dropdown-item-{KEY}`. You can use that to style the display of the item in the dropdown. + +Each item can contain the following keys: + +- `title`: the name of the custom format as shown in the dropdown +- `api`: the internal API method to call when the item is clicked, usually: `module.block.format`, `module.inline.format`, or `module.inline.clearformat` +- `args`: an object defining the custom format, containing the following: + - `tag`: the name of the tag to use for this custom format + - `class`: a class to apply to the tag (optional) + - `type`: either `set` (default, removes all existing classes, styles or attributes before applying your defined options), `add` (adds the new values leaving existing ones in place), `toggle` (either adds or removes the values depending on whether they are already set or not), or `remove` (removes the provided values). + - `attr`: an object defining attributes to set on a tag, for example: `{ "data-toggle": "modal" }` + - `style`: an object defining inline styles to add to the tag, for example: `{"background-color": "#ff9900"}` + + +## Examples + +Toggles a `h3.blue-styled` and `h3[style=color:red]`: + +```` json +{ + "blue-heading": { + "title": "Blue Heading", + "api": "module.block.format", + "args": { + "tag": "h3", + "class": "blue-styled", + "type": "toggle" + } + }, + "red-heading": { + "title": "Red Heading", + "api": "module.block.format", + "args": { + "tag": "h3", + "style": { + "color": "red" + }, + "type": "toggle" + } + } +} +```` + +Sets `div.callout.callout__info` and toggles inline `code`: + +```` json +{ + "info-callout": { + "title": "Info callout", + "api": "module.block.format", + "args": { + "tag": "div", + "class": "callout callout__info" + } + }, + "inline-code": { + "title": "Inline Code", + "api": "module.inline.format", + "args": { + "tag": "code", + "type": "toggle" + } + } +} +```` + +Clear inline formatting/styles: + +```` json +{ + "clear-format": { + "title": "Clear inline formatting", + "api": "module.inline.clearformat" + } +} +```` + +## Custom styling + +To show custom styling in the editor, [register a custom CSS file](Custom_CSS). diff --git a/en/04_Redactor/01_v3.x/Features/Custom_Plugins.md b/en/04_Redactor/01_v3.x/Features/Custom_Plugins.md new file mode 100644 index 00000000..230b88ac --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Custom_Plugins.md @@ -0,0 +1,46 @@ +With Redactor 3 for MODX you can also use [custom Redactor.js plugins](https://imperavi.com/redactor/examples/creating-plugins/sample-plugin/). + +## Loading custom plugins + +To load a plugin you need to do two things. + +- Add the URL to your plugin.js file to the `redactor.js` system setting. That system setting support comma-separating URLs, if you need multiple files. +- In the configurator, under Miscellaneous, add the name (only the name!) of your plugin to the Additional Plugins option. + +If your plugin requires custom CSS, you can use the `redactor.css` setting to load that. Make sure to scope your CSS appropriately as it will be loaded automatically across the MODX manager. [Learn more about custom styling](Custom_CSS). + +## Building custom plugins + +We're not going to cover all it takes to build a Redactor.js plugin. But here's an example of adding a button that pops up an alert: + +```js +(function($R) +{ + $R.add('plugin', 'alert', { + init: function(app) + { + this.toolbar = app.toolbar; + this.source = app.source; + }, + + start: function() { + var pos = this.toolbar.buttons.indexOf('alert'), + prev = null; + if (pos >= 1) { + prev = this.toolbar.buttons[pos - 1]; + } + var $button = this.toolbar.addButtonAfter(prev, 'alert', { + title: 'Alert', + api: 'plugin.alert.doAlert' + }); + $button.setIcon(''); + }, + + doAlert: function() { + window.alert('You\'ve now been alerted!') + } + }); +})(Redactor); +``` + +While a little more verbose than the examples offered by Imperavi, the code above makes sure that the user can decide where the button is inserted in the toolbar rather than only being appended to the end. diff --git a/en/04_Redactor/01_v3.x/Features/Dividers.md b/en/04_Redactor/01_v3.x/Features/Dividers.md new file mode 100644 index 00000000..9d2401c3 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Dividers.md @@ -0,0 +1,5 @@ +To keep the toolbar clean and easy to use, you can add dividers between buttons. To do so, add `divider` in the **Toolbar > Toolbar Buttons** input in a configuration set. + +The divider will be added where you add it in the definition, however some buttons (like table) have a hardcoded position in the list or are always added at the end which may make it work slightly different than expected. + +You can use the divider a maximum of 20 times in the toolbar. diff --git a/en/04_Redactor/01_v3.x/Features/Font_Options.md b/en/04_Redactor/01_v3.x/Features/Font_Options.md new file mode 100644 index 00000000..f308b3cc --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Font_Options.md @@ -0,0 +1,38 @@ +While we recommend using [Custom Formatting](Custom_Formatting) where possible, if desired you can give your users the ability to select the **text color**, **font family** and **font size** manually. + +On the **Toolbar** tab of the configurator, you can add the `fontcolor`, `fontfamily` and `fontsize` toolbar buttons to enable these options. + +These options will add span tags with inline styles. To use span tags with classes or to apply styles/classes to the block level tags, use [Custom Formatting](Custom_Formatting). + +## Customising available colors + +As of Redactor v3.1, you can customise the colors available in the text/font color (`fontcolor` button) dropdown. Both the "text" and "highlight" tabs use the same colors. + +On the **Formatting** tab of the configurator, enter a comma-separated list of colors (in hex notation, or another CSS-valid color name). Each row in the dropdown has room for 11 colors. + +The default colors are: + +``` +#ffffff, #000000, #eeece1, #1f497d, #4f81bd, #c0504d, #9bbb59, #8064a2, #4bacc6, #f79646, #ffff00, +#f2f2f2, #7f7f7f, #ddd9c3, #c6d9f0, #dbe5f1, #f2dcdb, #ebf1dd, #e5e0ec, #dbeef3, #fdeada, #fff2ca, +#d8d8d8, #595959, #c4bd97, #8db3e2, #b8cce4, #e5b9b7, #d7e3bc, #ccc1d9, #b7dde8, #fbd5b5, #ffe694, +#bfbfbf, #3f3f3f, #938953, #548dd4, #95b3d7, #d99694, #c3d69b, #b2a2c7, #b7dde8, #fac08f, #f2c314, +#a5a5a5, #262626, #494429, #17365d, #366092, #953734, #76923c, #5f497a, #92cddc, #e36c09, #c09100, +#7f7f7f, #0c0c0c, #1d1b10, #0f243e, #244061, #632423, #4f6128, #3f3151, #31859b, #974806, #7f6000 +``` + +## Customising available fonts + +As of Redactor v3.1, you can customise the available fonts for the `fontfamily` toolbar button. + +Provide a comma-separated list of font names (no quotes necessary) on the **Formatting** tab in the configurator, for `Font Family Options`. + +The default font families are: + +``` +Arial, Helvetica, Georgia, Times New Roman, Monospace +``` + +## Customising available font sizes + +It's not currently possible to change the available font sizes. They are hard-coded to `10, 11, 12, 14, 16, 18, 20, 24, 28, 30`. If customising these is important to you and you are unable of using the custom formatting instead, please let us know. diff --git a/en/04_Redactor/01_v3.x/Features/Image_Path_Mode.md b/en/04_Redactor/01_v3.x/Features/Image_Path_Mode.md new file mode 100644 index 00000000..aed3ded2 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Image_Path_Mode.md @@ -0,0 +1,44 @@ +As images in the manager and the front-end often require slightly different URL structures, Redactor will normalise inserted image URLs according to the image path mode. + +This is set on your configuration set, in the Media section. + +On this page we elaborate a bit on the different modes you can choose. This assumes the following settings: + +- Site URL is `https://mysite.com/modx/` +- Base URL is `/modx/` +- Image is located at `/modx/assets/image.jpg` +- The image relative URL (from the site's base url) is `assets/image.jpg` + +[TOC] + +## Relative mode + +The default and recommended value. + +In the manager, the url including base url is used to ensure it loads: `/modx/assets/image.jpg` + +In the frontend, the relative url is used: `assets/image.jpg` + +**Important**: when using relative mode, you need to have `` in your template, to ensure the image can be found. + +This mode is suitable for most single and multi-context uses. + +## Absolute mode + +In the manager, the url including base url is used: `/modx/assets/image.jpg` + +In the front-end, the base url is prepended to the image relative url to get to an absolute URL from the root of the domain: `/modx/assets/image.jpg` + +With this mode, you don't need the `` tag in the template. + +This mode may not work with all multi-context configurations. If your context for example sets a base url of `/de/`, the resulting url would be `/de/assets/image.jpg` even though the file might actually be located at `/assets/image.jpg`. In such cases, use Root relative mode instead. + +## Root relative mode + +Root relative mode is a combination of relative and absolute mode designed for multi-context setups where assets are located in the root of the domain, and not in a context-specific base url. + +In the manager and frontend, the would be `/assets/image.jpg` + +## Full mode + +In full mode, the entire site url is prepended to the relative image url. This makes it not very portable, and we don't encourage using this mode except for certain edge cases with subdomain-based context routing. diff --git a/en/04_Redactor/01_v3.x/Features/Image_Styles.md b/en/04_Redactor/01_v3.x/Features/Image_Styles.md new file mode 100644 index 00000000..f5d72989 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Image_Styles.md @@ -0,0 +1,21 @@ +With the **Image Styles** option (located under Media in the configurator), you can easily add a selection of classes that can be added to an image. + +The option requires a valid JSON structure, where an outer array contains objects with the keys `value` (containing the name of the class to add) and `label` (with a user-friendly name of the image style). + +For example, to add a "polaroid" class to an image: + +``` json +[ + { + "value": "polaroid", + "label": "Polaroid Photo" + } +] +``` + +(To make it affect the way an image is shown in the editor as well, you'll need to [register a custom CSS file](Custom_CSS)). + +When the use of `figure` tags is enabled (also on the Media tab in the configurator), the class will be added to the wrapping `
    ` tag for an image. When `figure` is disabled, or the figure tag could not be found, it will be added to the `` tag instead. + +When selecting a style for an image, all other styles are removed automatically. + diff --git a/en/04_Redactor/01_v3.x/Features/Inline_Styles.md b/en/04_Redactor/01_v3.x/Features/Inline_Styles.md new file mode 100644 index 00000000..012f8c6a --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Inline_Styles.md @@ -0,0 +1,14 @@ +By adding the `inlinestyle` button to your toolbar, you get access to a quick selection of inline styles to use. + +![Inline styles toolbar dropdown](../images/inlinestyle.jpg) + +- `` for marking parts of the text +- `` for inline code references +- `` +- `` for (keyboard) shortcuts +- superscript (``) +- subscript (``) + +The inline style options can't be customised. For more flexible inline styles, the [custom formatting functionality may be better suited](Custom_Formatting). + + diff --git a/en/04_Redactor/01_v3.x/Features/Link_Styles.md b/en/04_Redactor/01_v3.x/Features/Link_Styles.md new file mode 100644 index 00000000..e64aa005 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Link_Styles.md @@ -0,0 +1,33 @@ +With the **Link Styles** option (located under Links in the configurator), you can easily add a selection of classes that can be added to a link. + +The option requires a valid JSON structure, where an outer array contains objects with the keys `value` (containing the name of the class to add) and `label` (with a user-friendly name of the image style). + +For example, to add an "external" class to a link: + +``` json +[ + { + "value": "external", + "label": "External Link" + } +] +``` + +Or to offer Bootstrap button options: + +``` json +[ + { + "value": "btn btn-primary", + "label": "Primary Button" + }, + { + "value": "btn btn-secondary", + "label": "Secondary Button" + } +] +``` + +(To make it affect the way a link is shown in the editor as well, you'll need to [register a custom CSS file](Custom_CSS)). + +When selecting a style for a link, all other styles are removed automatically. diff --git a/en/04_Redactor/01_v3.x/Features/Properties.md b/en/04_Redactor/01_v3.x/Features/Properties.md new file mode 100644 index 00000000..0639bdfd --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Properties.md @@ -0,0 +1,7 @@ +New in Redactor 3 is the properties plugin. It allows you to add a class or ID to any block element. + +![The Properties plugin in action](../images/properties2.jpg) + +They're simple text inputs, requiring the user to enter the appropriate values. + +For more restricted or guided ways of adding of classes or IDs, use more specific functionality such as [custom formatting](Custom_Formatting), [image styles](Image_Styles), or [link styles](Link_Styles). \ No newline at end of file diff --git a/en/04_Redactor/01_v3.x/Features/Source.md b/en/04_Redactor/01_v3.x/Features/Source.md new file mode 100644 index 00000000..328d7ba6 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Source.md @@ -0,0 +1,15 @@ +The source mode is shown when clicking the HTML icon in the toolbar and lets you see/change the raw HTML source for the content. + +## Enable source mode + +To enable it, make sure "Allow Source Mode" is enabled in the Source section of the configurator, and add `html` to your toolbar buttons under Toolbar where you want the button to be available. + +## Syntax highlighting + +If desired, you can enable CodeMirror syntax highlighting for easier use of the source. Under the "Source" section of the configurator, make sure "Enable CodeMirror" is enabled. + +## Beautifying source code + +By enabling _Beautify source code_ in the Source section, the markup can be reformatted for you, adding the proper indentation and newlines and such. This uses [js-beautify](https://github.com/beautify-web/js-beautify). + +Beautifying the markup will happen at most once every 3 seconds while editing content. It can also be forced by toggling the source view. If you're experiencing performance issues on large pages, please contact support. diff --git a/en/04_Redactor/01_v3.x/Features/Text_Expander.md b/en/04_Redactor/01_v3.x/Features/Text_Expander.md new file mode 100644 index 00000000..46edc0a9 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Text_Expander.md @@ -0,0 +1,22 @@ +The text expander lets you define shortcuts that insert a longer content. + +Once defined, you type the shortcut, follow it with a space, and the expanded text will be inserted. + +Text expanders are configured in your configuration set under Text Utilities. + +Text expanders use a JSON format with arrays nested in an array. The first element in the nested array is the shortcut, and the second element is the text to insert. + +For example: + +```` json +[ + [ + "lorem", + "Lorem ipsum dolor sit amet..." + ], + [ + "modmore", + "modmore - More for MODX!" + ] +] +```` diff --git a/en/04_Redactor/01_v3.x/Features/Toolbar.md b/en/04_Redactor/01_v3.x/Features/Toolbar.md new file mode 100644 index 00000000..d62562db --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Toolbar.md @@ -0,0 +1,47 @@ +--- +title: Toolbar Buttons +--- + +The toolbar is the most important aspect of Redactor, providing you with the buttons to add markup and media. + +It is primarily configured by the list of buttons, in the Toolbar section of the configurator. The available list of buttons is shown below that field. + +[TOC] + +## Buttons + +- Formatting and text: format (includes [custom formatting](Custom_Formatting)), bold, italic, deleted, underline, sup, sub, fontcolor, fontfamily, fontsize, [inlinestyle](Inline_Styles), textdirection, alignment +- Lists: lists, ol, ul, indent, outdent +- Media: link, image, file, video, widget +- Editor: redo, undo, fullscreen, [divider](Dividers) +- Others: [html](Source), line, [properties](Properties), specialchars, table, download + +## Redactor Plugins + +Whenever a toolbar button requires a Redactor plugin, it is automatically initialised. + +In some cases, the positioning of buttons initialised by a plugin cannot be changed. This has to do with how plugins are initialised one at a time, and that buttons added to the toolbar are added either at the end or relative to specific buttons. + +The following plugins have hardcoded positions in the toolbar which cannot be changed: + +- inlinestyle, always added after the format button +- table, always added before the link button +- video, always added after the image button + +As of Redactor v3.1, plugins that previously had no defined position that would always get added at the end of the toolbar, will now position themselves properly, based on their location in the buttons configuration. This affected the following plugins before v3.1: `alignment, clips, fontcolor, fontfamily, fontsize, fullscreen, properties, specialchars, textdirection, variable, widget`. + +If you still seeing odd positioning of toolbar buttons in v3.1+ that's different from your configuration, make sure the buttons with a fixed position (inlinestyle, table, video) are configured in their hardcoded position (e.g. make sure `table` is before `link` in your toolbar buttons configuration). + +## Examples + +Redactor ships with a Minimal and Standard configuration out of the box. These use the following button configuration. + +Minimal: + +> format, divider, bold, italic, underline, deleted, divider, link, image + +Standard: + +> format, bold, italic, underline, divider, table, link, image, file, divider, ol, ul, indent, outdent, divider, redo, undo, divider, html + +![Minimal vs Standard configuration example](../images/min-vs-standard.png) \ No newline at end of file diff --git a/en/04_Redactor/01_v3.x/Features/Upload_Filename_Sanitization.md b/en/04_Redactor/01_v3.x/Features/Upload_Filename_Sanitization.md new file mode 100644 index 00000000..48e78c64 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Upload_Filename_Sanitization.md @@ -0,0 +1,11 @@ +On upload, Redactor will sanitize file names to make sure they're clean. + +This uses a few system settings: + +- `redactor.sanitize_pattern`, contains a REGEX pattern of acceptable characters. Defaults to `/([[:alnum:]_\.-]*)/` +- `redactor.sanitize_replace` contains the value invalid characters are replaced with, defaults to `_` +- `redactor.translit` can be set to a transliteration strategy. `iconv` is included; others can be enabled with a third party package such as [Translit](https://modx.com/extras/package/translit). If you've configured the MODX core `translit` setting, you can leave `redactor.translit` empty to inherit the same configuration. +- `redactor.translit_class` +- `redactor.translit_class_path` + +To disable file name cleaning (which is not recommended unless you use a separate implementation), disable _Clean filenames_ in the Media - Uploads section of the configurator. diff --git a/en/04_Redactor/01_v3.x/Features/Variables.md b/en/04_Redactor/01_v3.x/Features/Variables.md new file mode 100644 index 00000000..4763273b --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/Variables.md @@ -0,0 +1,9 @@ +Variables lets you define non-editable placeholders to insert into the content. + +Once a variable is insert, it can be changed to other variables or removed, but their text remains fixed. + +This is useful when users want to add (simple) MODX tags (e.g. `[[*pagetitle]]`, `[[$something.else]]`) in a way that prevents them from accidentally breaking it. + +To specify variables, enter them in your configuration set under **Text Utilities > Variables**, separating each variable with a comma. + +Variables are saved with a `` wrapper to make sure that the variable remains uneditable when the page is reloaded. \ No newline at end of file diff --git a/en/04_Redactor/01_v3.x/Features/index.md b/en/04_Redactor/01_v3.x/Features/index.md new file mode 100644 index 00000000..c838ccb9 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/index.md @@ -0,0 +1,26 @@ +--- +title: Feature Configuration +--- + +The configuration page in the manager includes a description for most fields to help you understand what they do. We don't repeat that here for brevity. + +Some features however, are a bit more powerful or have more complicated configuration formats. This section explains those in more detail. + +- [Autoparse](Autoparse) +- [Clips](Clips) +- [Custom CSS](Custom_CSS) +- [Custom Formatting](Custom_Formatting) +- [Custom Plugins](Custom_Plugins) +- [Dividers](Dividers) +- [Font options (color, family and size)](Font_Options) +- [Image Path Mode (aka base urls mode)](Image_Path_Mode) +- [Image Styles](Image_Styles) +- [Inline Styles](Inline_Styles) +- [Link Styles](Link_Styles) +- [modAI Support](modAI) +- [Properties](Properties) +- [Source mode](Source) +- [Text Expander](Text_Expander) +- [Toolbar Buttons](Toolbar) +- [Upload filename sanitization](Upload_Filename_Sanitization) +- [Variables](Variables) diff --git a/en/04_Redactor/01_v3.x/Features/modAI.md b/en/04_Redactor/01_v3.x/Features/modAI.md new file mode 100644 index 00000000..fe358668 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Features/modAI.md @@ -0,0 +1,117 @@ +As of Redactor v3.3, we provide a [modAI integration](https://extras.modx.com/package/modai) integration that lets you use various AI Large Language Models to edit or generate content. + +To use, add the `modai` button to your toolbar in the Redactor Configurator. Now, highlight the text you wish to edit (or don't to use the full content as context), and click the button to open the modAI Assistant interface. + +![Screenshot showing the "Edit with AI" button in the Redactor toolbar](../images/modai-button.jpg) + +## Quick Prompts + +Optionally, you can configure the **modAI Prompts** at the bottom of the Toolbar tab in the configurator. When configured, these show up as a dropdown menu under the button. + +![Screenshot showing an example of the actions availalbe as quick prompts](../images/modai-quickprompts.jpg) + +The quick prompts take in the selection, and immediately fire off the configured prompt. This makes it easy to perform repeated actions, add translation options, and so on. + +The default value contains a bunch of useful example prompts: + +```json +[ + { + "label": "Proofread", + "prompt": "Proofread the text and fix any spelling or grammar mistakes" + }, + { + "label": "Clarify", + "prompt": "Improve this copy to eliminate unclear thoughts or awkward phrasing" + }, + { + "label": "Add a Paragraph", + "prompt": "- Add a paragraph to this copy.\n- You can rewrite the other copy if it enhances the copy\n- Format it with HTML markup so it will work in the editor when pasted in." + }, + { + "label": "Add a Sentence", + "prompt": "- Add a sentence to this copy that will improve it\n- You can rewrite the other copy if it enhances the copy\n- Format it with HTML markup so it will work in the editor when pasted in." + }, + { + "label": "Remove a Sentence", + "prompt": "- Remove a sentence from this copy. Format it with HTML markup so it will work in the editor when pasted in." + }, + { + "label": "Cut in Half", + "prompt": "- Condense this copy to roughly half of its current length\n- Maintain important concepts and key topics\n- Combine or eliminate paragraphs if it makes sense and helps with readability\n- Format it with HTML markup so it will work in the editor when pasted in." + }, + { + "label": "Use formal tone", + "prompt": "Rewrite this with a formal tone." + }, + { + "label": "Use conversational tone", + "prompt": "Rewrite this with a casual, conversational tone." + }, + { + "label": "Use professional tone", + "prompt": "Rewrite this with a professional tone." + }, + { + "label": "Use humorous tone", + "prompt": "Rewrite this with a humorous tone." + }, + { + "label": "Translate to English (CA)", + "prompt": "Localise or translate this to Canadian English" + }, + { + "label": "Translate to English (UK)", + "prompt": "Localise or translate this to British English" + }, + { + "label": "Translate to English (US)", + "prompt": "Localize or translate this to American English" + }, + { + "label": "Translate to Dutch", + "prompt": "Translate this to Dutch" + }, + { + "label": "Translate to French", + "prompt": "Translate this to French" + }, + { + "label": "Translate to German", + "prompt": "Translate this to German" + }, + { + "label": "Translate to Italian", + "prompt": "Translate this to Italian" + }, + { + "label": "Translate to Japanese", + "prompt": "Translate this to Japanese" + }, + { + "label": "Translate to Korean", + "prompt": "Translate this to Korean" + }, + { + "label": "Translate to Portuguese (BR)", + "prompt": "Translate this to Brazillian Portugese" + }, + { + "label": "Translate to Portuguese (PT)", + "prompt": "Translate this to European Portugese" + }, + { + "label": "Translate to Russian", + "prompt": "Translate this to Russian" + }, + { + "label": "Translate to Spanish", + "prompt": "Translate this to Spanish" + } +] +``` + + + + + diff --git a/en/04_Redactor/01_v3.x/Permissions.md b/en/04_Redactor/01_v3.x/Permissions.md new file mode 100644 index 00000000..024bf9b7 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Permissions.md @@ -0,0 +1,47 @@ +If desired, you can limit access to the Configurator using the MODX permissions system. + +On installation, Redactor will automatically give full configurator access to all user groups with access to the manager. After that, permissions are not changed unless you remove the policy from the administrator user group again. + +[TOC] + +## Available Permissions + +A default Access Policy is created on installation which includes all permissions. + +The following permissions are included: + +- `redactor_configurator` gives access to the Redactor Configurator component, including the menu item under Extras. +- `redactor_sets_view` gives access to view the configuration for a specific configuration (but not save the changes) +- `redactor_sets_create` allows creating new sets; also requires `redactor_save_sets` +- `redactor_sets_save` allows saving existing sets +- `redactor_sets_export` allows creating an XML export of one or all sets +- `redactor_sets_import` allows importing sets from an XML import if `redactor_sets_create`, `redactor_sets_save` and `redactor_sets_delete` are also assigned +- `redactor_sets_delete` allows deleting a set. + +To duplicate sets, both `redactor_sets_create` and `redactor_sets_save` permission are needed. + +## Setting custom policies + +### Step 1: Create the Access Policy + +The first thing to do is creating an access policy. Go to _System_ > _Access Control Lists_ and hop into the _Access Policies_ tab. Click on _Create Access Policy_ and fill in the window. Enter a name and description that describes your policy (e.g. "Redactor Basic Access"), but most importantly **select RedactorTemplate as the policy template**. Save the new Policy. + +Find the new policy in the grid and choose _Update Policy_ in the right click menu. + +Now you can choose which permissions the user should have. We've listed them in the previous section. + +Select the desired permissions, save the Access Policy, and choose close to return to the Access Control Lists page in the manager. + +### Step 2: Add the Policy to a User Group + +Now you can add the Access Policy to a user group. + +On the User Groups & Users tab choose the user group you would like to give limited access to the configurator with your access policy. + +Right click the user group and choose _Update User Group_. + +On the new page, go to _Permissions_ > _Context Access_. Hit _Add Context_ and in the window select the `mgr` context, a minimum role of member (9999), and the access policy you created in the previous step. + +### Step 3: flush permissions + +While manager sessions typically flush permissions automatically, you can flush the sessions via Manage > Flush permissions to make sure sessions are reloaded. diff --git a/en/04_Redactor/01_v3.x/Shortcodes.md b/en/04_Redactor/01_v3.x/Shortcodes.md new file mode 100644 index 00000000..7fd2d749 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Shortcodes.md @@ -0,0 +1,22 @@ +Shortcodes allow you to set the block-level element without using the keyboard. It's a great companion to air mode and a power-user feature to keep typing without needing to use the mouse to select formatting options. + + + +To use a shortcode, start typing the shortcode at the start of an empty line. Redactor will recognise the shortcode and adjust the formatting right away. + +The following shortcodes are recognised: + +- `p.` for a paragraph +- `quote.` for a blockquote +- `pre.` for a code block +- `h1.` for a heading level 1 +- `h2.` for a heading level 2 +- `h3.` for a heading level 3 +- `h4.` for a heading level 4 +- `h5.` for a heading level 5 +- `h6.` for a heading level 6 +- `*.` for an unordered list + +Make sure to combine the use of shortcodes with the [available keyboard shortcuts](Shortcuts). diff --git a/en/04_Redactor/01_v3.x/Shortcuts.md b/en/04_Redactor/01_v3.x/Shortcuts.md new file mode 100644 index 00000000..51975f53 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Shortcuts.md @@ -0,0 +1,32 @@ +Redactor comes with the following built-in shortcuts. + +## Editor shortcuts + +| Action | Windows | Mac | +|--------|---------|-----| +| Clear inline formatting | ctrl+shift+m | meta+shift+m | +| Toggle bold style | ctrl+b | meta+b | +| Toggle italics style | ctrl+i | meta+i | +| Toggle underline style | ctrl+u | meta+u | +| Toggle `` style | ctrl+h | meta+h | +| Toggle `` style | ctrl+l (lowercase L) | meta+l | +| Toggle heading level 1 | ctrl+alt+1 | meta+alt+1 | +| Toggle heading level 2 | ctrl+alt+2 | meta+alt+2 | +| Toggle heading level 3 | ctrl+alt+3 | meta+alt+3 | +| Toggle heading level 4 | ctrl+alt+4 | meta+alt+4 | +| Toggle heading level 5 | ctrl+alt+5 | meta+alt+5 | +| Toggle heading level 6 | ctrl+alt+6 | meta+alt+6 | +| Toggle ordered list | ctrl+shift+7 | meta+shift+7 | +| Toggle unordered list | ctrl+shift+8 | meta+shift+8 | +| Insert hard tab (`\t`) | shift+tab | shift+tab | +| Indent list item | tab, ctrl+] | tab, meta+] | +| Outdent list item | shift+tab (in list), ctrl+[ | shift+tab (in list), meta+[ | + +## Configurator shortcuts + +In the configuration set configurator: + +| Action | Windows | Mac | +|--------|---------|-----| +| Save the configuration set | ctrl+s | meta+s | +| Export the configuration set | ctrl+e | meta+e | diff --git a/en/04_Redactor/01_v3.x/Themes/Custom.md b/en/04_Redactor/01_v3.x/Themes/Custom.md new file mode 100644 index 00000000..f7161250 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Themes/Custom.md @@ -0,0 +1,65 @@ +--- +title: Custom Themes +--- + +Custom Themes are CSS targetting specific elements of the Redactor editor. They can target just the editor and toolbar, or also affect the actual styling of the content inside it. + +[TOC] + +## Theme Requirements + +- The theme css file must be loaded into the manager. You can add the URL for a CSS file to the `redactor.css` system setting to load it whenever Redactor is used. +- The theme must be enabled by setting its name into the Appearance > Toolbar theme setting. +- All CSS rules **must** be scoped to `.redactor-theme-.redactor-box`. If you use Sass, use this as a wrapping rule. + +Use the browsers' developer tools to inspect the markup of the editor to find the right classes to target your custom styling. + +Note that some elements in the content might have a different markup in the editor compared to the markup that is outputted or shown in source view. + +## Example + +Changing the background color of the toolbar for theme "mycolor" with Sass: + +``` scss +.redactor-theme-mycolor.redactor-box { + .redactor-toolbar-wrapper { + background: #FF9900; + padding-bottom: 16px; + border-radius: 2px 2px 0 0; + } +} +``` + +or plain CSS: + +```css +.redactor-theme-mycolor.redactor-box .redactor-toolbar-wrapper { + background: #FF9900; + padding-bottom: 16px; + border-radius: 2px 2px 0 0; +} +``` + +## Supporting dark mode toggle + +To support the dark mode toggle in your theme, add additional styling when the `redactor-theme__dark` class is present on the `redactor-box`. + +For example: + +``` scss +.redactor-theme-mycolor.redactor-box { + .redactor-toolbar-wrapper { + background: #FF9900; + padding-bottom: 16px; + border-radius: 2px 2px 0 0; + } + + &.redactor-theme__dark { + .redactor-toolbar-wrapper { + background: #6c3600; + } + } +} +``` + + diff --git a/en/04_Redactor/01_v3.x/Themes/dark.jpg b/en/04_Redactor/01_v3.x/Themes/dark.jpg new file mode 100644 index 00000000..32a97405 Binary files /dev/null and b/en/04_Redactor/01_v3.x/Themes/dark.jpg differ diff --git a/en/04_Redactor/01_v3.x/Themes/default.jpg b/en/04_Redactor/01_v3.x/Themes/default.jpg new file mode 100644 index 00000000..f02b1c47 Binary files /dev/null and b/en/04_Redactor/01_v3.x/Themes/default.jpg differ diff --git a/en/04_Redactor/01_v3.x/Themes/index.md b/en/04_Redactor/01_v3.x/Themes/index.md new file mode 100644 index 00000000..ff42b9d4 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Themes/index.md @@ -0,0 +1,65 @@ +The Redactor editor can be themed with CSS. Most themes only affect the editor and toolbar, but [custom themes can also change the content styling](Custom). + +On this page, we list the available built-in themes. + +[TOC] + +## Standard Themes + +### default + +The default theme is almost the standard theme from [imperavi](https://imperavi.com/redactor/) with only some minor changes, like adding a background that matches MODX input fields. + +![Default Redactor theme](default.jpg) + +### redactor2 + +The redactor2 theme mimics the styling from Redactor 2.x. It's not an exact match, but is a lot closer and can help if you're having trouble adjusting to the new design. + +![Redactor 2 inspired theme for Redactor 3](redactor2.jpg) + +### minimal + +The minimal theme provides a flat toolbar without shadows or rounded borders. Taken some inspiration from TinyMCE. + +![Minimal theme for Redactor](minimal.jpg) + +### dark + +The dark theme inverses the color while using a blue for headers and links. + +![Dark theme for Redactor 3](dark.jpg) + +Note that a dynamic dark mode is also available for most themes; add the `toggledark` button to your toolbar configuration to use it. More on that below. + +### pride + +Looking to spread some _love is love_? The pride theme splashes a rainbows on your toolbar. (Unicorns are still awaiting delivery.) + +![Pride theme for Redactor 3](pride.jpg) + +### rebeccapurple + +A very special shade of purple indeed, [rebeccapurple exists in memory of Eric Meyer's daughter](https://meyerweb.com/eric/thoughts/2014/06/19/rebeccapurple/). + +![rebeccaapurple theme for Redactor 3](rebeccapurple.jpg) + +## Dark Mode + +Aside from the Dark theme, shown before, you can also use a dynamic dark mode. This functions as a toggle button in the toolbar, and switches to a dark version of the chosen theme. + +To use it, add `toggledark` to your Toolbar Buttons in the configurator. Then find the toggle button in the toolbar. + +The dark mode works best with the `default`, `redactor2` and `minimal` themes. Shown below is the toggling in action with the redactor2 theme. + + + +When toggling the default theme, that switches to the dark theme. The other themes have their own dark styles which may be slightly different. + +Toggling the dark theme does not have any effect. + +## Custom themes + +[Learn more about custom themes](Custom). diff --git a/en/04_Redactor/01_v3.x/Themes/minimal.jpg b/en/04_Redactor/01_v3.x/Themes/minimal.jpg new file mode 100644 index 00000000..1dc4016f Binary files /dev/null and b/en/04_Redactor/01_v3.x/Themes/minimal.jpg differ diff --git a/en/04_Redactor/01_v3.x/Themes/pride.jpg b/en/04_Redactor/01_v3.x/Themes/pride.jpg new file mode 100644 index 00000000..5370e0e5 Binary files /dev/null and b/en/04_Redactor/01_v3.x/Themes/pride.jpg differ diff --git a/en/04_Redactor/01_v3.x/Themes/rebeccapurple.jpg b/en/04_Redactor/01_v3.x/Themes/rebeccapurple.jpg new file mode 100644 index 00000000..0e42f79e Binary files /dev/null and b/en/04_Redactor/01_v3.x/Themes/rebeccapurple.jpg differ diff --git a/en/04_Redactor/01_v3.x/Themes/redactor2.jpg b/en/04_Redactor/01_v3.x/Themes/redactor2.jpg new file mode 100644 index 00000000..9e20ecc8 Binary files /dev/null and b/en/04_Redactor/01_v3.x/Themes/redactor2.jpg differ diff --git a/en/04_Redactor/01_v3.x/Themes/themes.png b/en/04_Redactor/01_v3.x/Themes/themes.png new file mode 100644 index 00000000..3399b3d4 Binary files /dev/null and b/en/04_Redactor/01_v3.x/Themes/themes.png differ diff --git a/en/04_Redactor/01_v3.x/Themes/themes.sketch b/en/04_Redactor/01_v3.x/Themes/themes.sketch new file mode 100644 index 00000000..7de0e07e Binary files /dev/null and b/en/04_Redactor/01_v3.x/Themes/themes.sketch differ diff --git a/en/04_Redactor/01_v3.x/Upgrades/From_2.x.md b/en/04_Redactor/01_v3.x/Upgrades/From_2.x.md new file mode 100644 index 00000000..1d3999e7 --- /dev/null +++ b/en/04_Redactor/01_v3.x/Upgrades/From_2.x.md @@ -0,0 +1,47 @@ +--- +title: Upgrading from Redactor 2.x +--- + +When upgrading from 2.x, expect a new and refreshed editor. Many features will be familiar, but some have also been removed or operate differently now. And of course, there's a lot of new features for you to use as well. + +## First Upgrade + +During the first upgrade to Redactor 3, your v2 system settings will automatically be converted into a [configuration set](../Configuration_Sets) named "Imported from Redactor 2". + +This imported set will be as close as a match to your old configuration as possible, but keep in mind not every old setting has a new option. + +**Your imported set will be automatically enabled.** Please test it to make sure it was properly imported and works the way you expect it to. + +To help ease with upgrading when using custom CSS, the v2 "redactor-editor" class is added to your imported configuration set (in Appearance > Content style class); this will not be present on the standard configuration sets. [Learn more about custom styling in v3](../Features/Custom_CSS) + +The JSON structure for custom formatting has changed in v3 and will need to be manually updated. + +**Important:** downgrading from 3 to 2 is **not supported**. If you're not sure yet if you want to start using Redactor 3 right away, test the upgrade on a development site and only upgrade production when you're happy. + +Old system settings from v2, with a few exceptions, are removed on the first upgrade to v3. + +## Tip: start fresh + +While the automatic import is useful, we do recommend configuring Redactor 3 from scratch. Take a good tour of the new configuration sets to find out what Redactor 3 can do and use this as an opportunity to refresh your configuration. + +[The Redactor 3 Quickstart](../Quickstart) takes you through the highlights. + +## Dropped or changed features + +Please note this list may be incomplete + +- Allowed/denied tags and cleanup in general works differently now. See the Cleanup tab for details of what you can configure in v3. +- The image float margin from v2 has changed. Previously you would set a margin for left and right floats separately, in v3 you set a single margin (in the Media tab) which will automatically be applied to the proper side of the image. +- Source code highlighting with Ace is no longer supported. Only Codemirror is now available (enabled by default). +- The syntax for some plugins (like Clips) has changed. In most cases these will be automatically converted by the configurator. See the configurator for details. +- Changing the available colors for the fontcolor plugin is no longer supported. + +The following custom plugins are no longer supported. Let us know if you think we should rebuild them for v3. + +- replacer (find & replace window) +- speek (read content out loud) +- contrast +- zoom +- imagepx +- imageurl +- breadcrumb diff --git a/en/04_Redactor/01_v3.x/images/contentblocks-input.jpg b/en/04_Redactor/01_v3.x/images/contentblocks-input.jpg new file mode 100644 index 00000000..05081b34 Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/contentblocks-input.jpg differ diff --git a/en/04_Redactor/01_v3.x/images/darkmode.gif b/en/04_Redactor/01_v3.x/images/darkmode.gif new file mode 100644 index 00000000..5f3fc55d Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/darkmode.gif differ diff --git a/en/04_Redactor/01_v3.x/images/darkmode.jpg b/en/04_Redactor/01_v3.x/images/darkmode.jpg new file mode 100644 index 00000000..fdc71752 Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/darkmode.jpg differ diff --git a/en/04_Redactor/01_v3.x/images/darkmode.mp4 b/en/04_Redactor/01_v3.x/images/darkmode.mp4 new file mode 100644 index 00000000..b738d88a Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/darkmode.mp4 differ diff --git a/en/04_Redactor/01_v3.x/images/inlinestyle.jpg b/en/04_Redactor/01_v3.x/images/inlinestyle.jpg new file mode 100644 index 00000000..f7efa2ac Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/inlinestyle.jpg differ diff --git a/en/04_Redactor/01_v3.x/images/introtext.jpg b/en/04_Redactor/01_v3.x/images/introtext.jpg new file mode 100644 index 00000000..4be9dae3 Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/introtext.jpg differ diff --git a/en/04_Redactor/01_v3.x/images/menu-entry.jpg b/en/04_Redactor/01_v3.x/images/menu-entry.jpg new file mode 100644 index 00000000..32dc03a7 Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/menu-entry.jpg differ diff --git a/en/04_Redactor/01_v3.x/images/min-vs-standard.png b/en/04_Redactor/01_v3.x/images/min-vs-standard.png new file mode 100644 index 00000000..098d3ce3 Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/min-vs-standard.png differ diff --git a/en/04_Redactor/01_v3.x/images/modai-button.jpg b/en/04_Redactor/01_v3.x/images/modai-button.jpg new file mode 100644 index 00000000..e54aff5b Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/modai-button.jpg differ diff --git a/en/04_Redactor/01_v3.x/images/modai-quickprompts.jpg b/en/04_Redactor/01_v3.x/images/modai-quickprompts.jpg new file mode 100644 index 00000000..8bc31afc Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/modai-quickprompts.jpg differ diff --git a/en/04_Redactor/01_v3.x/images/properties2.jpg b/en/04_Redactor/01_v3.x/images/properties2.jpg new file mode 100644 index 00000000..40f88b62 Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/properties2.jpg differ diff --git a/en/04_Redactor/01_v3.x/images/shortcodes-poster.jpg b/en/04_Redactor/01_v3.x/images/shortcodes-poster.jpg new file mode 100644 index 00000000..f24f7b9f Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/shortcodes-poster.jpg differ diff --git a/en/04_Redactor/01_v3.x/images/shortcodes.gif b/en/04_Redactor/01_v3.x/images/shortcodes.gif new file mode 100644 index 00000000..9ece5dc2 Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/shortcodes.gif differ diff --git a/en/04_Redactor/01_v3.x/images/shortcodes.mp4 b/en/04_Redactor/01_v3.x/images/shortcodes.mp4 new file mode 100644 index 00000000..c8bf75cc Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/shortcodes.mp4 differ diff --git a/en/04_Redactor/01_v3.x/images/template-properties.jpg b/en/04_Redactor/01_v3.x/images/template-properties.jpg new file mode 100644 index 00000000..1dc5d3ce Binary files /dev/null and b/en/04_Redactor/01_v3.x/images/template-properties.jpg differ diff --git a/en/04_Redactor/01_v3.x/index.md b/en/04_Redactor/01_v3.x/index.md new file mode 100644 index 00000000..c34e94f5 --- /dev/null +++ b/en/04_Redactor/01_v3.x/index.md @@ -0,0 +1,11 @@ +--- +title: Redactor 3.x +--- + +Redactor 3 makes editing your content a breeze, with straightforward media management, a clean theme-able interface, and a powerful configurator to help you make the most of all its power. + +Redactor 3 is the latest implementation of [Imperavi's Redactor.js](https://imperavi.com/redactor/) for MODX. + +- Upgrading from 2.x? [Start here »](Upgrades/From_2.x) +- New to Redactor? [Start with the Quickstart Guide »](Quickstart) +- Looking for information on what Redactor can do, licenses, prices, or reviews? [Back to modmore.com](https://modmore.com/redactor/) diff --git a/en/04_Redactor/01_v2.x/00_Upgrading_from_Redactor_1.x_to_2.0.md b/en/04_Redactor/98_v2.x/00_Upgrading_from_Redactor_1.x_to_2.0.md similarity index 98% rename from en/04_Redactor/01_v2.x/00_Upgrading_from_Redactor_1.x_to_2.0.md rename to en/04_Redactor/98_v2.x/00_Upgrading_from_Redactor_1.x_to_2.0.md index 3c2e0dca..72ed67e5 100755 --- a/en/04_Redactor/01_v2.x/00_Upgrading_from_Redactor_1.x_to_2.0.md +++ b/en/04_Redactor/98_v2.x/00_Upgrading_from_Redactor_1.x_to_2.0.md @@ -2,7 +2,7 @@ title: Upgrading from Redactor 1.x to 2.0 --- -Redactor 2.0 is a major release, which brings with it major changes. New features and improvements have been added, but some older features have also been removed or replaced. While we've tried to make the upgrade as seamless as possible, some breaking changes have been inevitable. This document discusses the removed or replaced features. For more information about all the new and improved features, please review the [2.0 announcement blog](https://www.modmore.com/blog/2015/announcing-redactor-2.0/). +Redactor 2.0 is a major release, which brings with it major changes. New features and improvements have been added, but some older features have also been removed or replaced. While we've tried to make the upgrade as seamless as possible, some breaking changes have been inevitable. This document discusses the removed or replaced features. For more information about all the new and improved features, please review the [2.0 announcement blog](https://modmore.com/blog/2015/announcing-redactor-2.0/). Before upgrading to Redactor 2.0, we recommend making a backup of the Redactor files and your system settings database table, just in case you need to revert. diff --git a/en/04_Redactor/01_v2.x/01_Installation.md b/en/04_Redactor/98_v2.x/01_Installation.md similarity index 92% rename from en/04_Redactor/01_v2.x/01_Installation.md rename to en/04_Redactor/98_v2.x/01_Installation.md index 392124da..5025c872 100755 --- a/en/04_Redactor/01_v2.x/01_Installation.md +++ b/en/04_Redactor/98_v2.x/01_Installation.md @@ -1,8 +1,8 @@ -To get started with Redactor, or one of our other Extras, you will first need to have a license available. There are several options, including buying single licenses as you go, and an unlimited license offer so you always have licenses to use. The available options and their costs can be found on the [Redactor Pricing](https://www.modmore.com/redactor/pricing/) page. +To get started with Redactor, or one of our other Extras, you will first need to have a license available. There are several options, including buying single licenses as you go, and an unlimited license offer so you always have licenses to use. The available options and their costs can be found on the [Redactor Pricing](https://modmore.com/redactor/pricing/) page. -When you have a license available, you will need to download the package to your MODX site. This is done using the Package Installer, which will need to connect to our Package Provider. To connect to our Package Provider, you can create an [API Key in your account](https://www.modmore.com/account/api-keys/). +When you have a license available, you will need to download the package to your MODX site. This is done using the Package Installer, which will need to connect to our Package Provider. To connect to our Package Provider, you can create an [API Key in your account](https://modmore.com/account/api-keys/). -To set up the provider and download the extra, see the [Package Provider page](https://www.modmore.com/about/package-provider/). +To set up the provider and download the extra, see the [Package Provider page](https://modmore.com/about/package-provider/). After a successful installation, Redactor will be set as the default Rich Text Editor, and it will replace the content field with the Redactor editor, while enhancing rich text template variables as well. You can customize behavior and looks of the editor with the many Redactor [configuration options](Configure_Redactor). These settings can be found on the System » System Settings page in your MODX Manager, under the redactor namespace (that's the first dropdown that defaults to "core"). Any of these settings can also be overridden on a user group, user or context level by simply creating new settings at the appropriate level with the same setting key. diff --git a/en/04_Redactor/01_v2.x/02_Configure_Redactor.md b/en/04_Redactor/98_v2.x/02_Configure_Redactor.md similarity index 100% rename from en/04_Redactor/01_v2.x/02_Configure_Redactor.md rename to en/04_Redactor/98_v2.x/02_Configure_Redactor.md diff --git a/en/04_Redactor/01_v2.x/03_Managing_Media.md b/en/04_Redactor/98_v2.x/03_Managing_Media.md similarity index 100% rename from en/04_Redactor/01_v2.x/03_Managing_Media.md rename to en/04_Redactor/98_v2.x/03_Managing_Media.md diff --git a/en/04_Redactor/01_v2.x/04_Custom_Formatting.md b/en/04_Redactor/98_v2.x/04_Custom_Formatting.md similarity index 100% rename from en/04_Redactor/01_v2.x/04_Custom_Formatting.md rename to en/04_Redactor/98_v2.x/04_Custom_Formatting.md diff --git a/en/04_Redactor/01_v2.x/05_Images_and_Base_URLs.md b/en/04_Redactor/98_v2.x/05_Images_and_Base_URLs.md similarity index 100% rename from en/04_Redactor/01_v2.x/05_Images_and_Base_URLs.md rename to en/04_Redactor/98_v2.x/05_Images_and_Base_URLs.md diff --git a/en/04_Redactor/01_v2.x/06_Component_Usage.md b/en/04_Redactor/98_v2.x/06_Component_Usage.md similarity index 98% rename from en/04_Redactor/01_v2.x/06_Component_Usage.md rename to en/04_Redactor/98_v2.x/06_Component_Usage.md index 62e33dbf..41a12fbd 100755 --- a/en/04_Redactor/01_v2.x/06_Component_Usage.md +++ b/en/04_Redactor/98_v2.x/06_Component_Usage.md @@ -86,6 +86,6 @@ closeAction: 'close' ## Done! -This requires at least Redactor 1.2. This method should also work for other editors that are available for MODX, however your mileage may vary. Consult the documentation or ask the developer to see if other editors you prefer to use supports this approach. Or, you know, [buy Redactor](https://www.modmore.com/redactor/pricing/). ;) +This requires at least Redactor 1.2. This method should also work for other editors that are available for MODX, however your mileage may vary. Consult the documentation or ask the developer to see if other editors you prefer to use supports this approach. Or, you know, [buy Redactor](https://modmore.com/redactor/pricing/). ;) We have tested the Redactor integration in, among others, FAQ Manager, MoreGallery, Articles, mxCalendar and ContentBlocks. diff --git a/en/04_Redactor/01_v2.x/07_Custom_Redactor_TV.md b/en/04_Redactor/98_v2.x/07_Custom_Redactor_TV.md similarity index 100% rename from en/04_Redactor/01_v2.x/07_Custom_Redactor_TV.md rename to en/04_Redactor/98_v2.x/07_Custom_Redactor_TV.md diff --git a/en/04_Redactor/01_v2.x/08_Uploadcare.md b/en/04_Redactor/98_v2.x/08_Uploadcare.md similarity index 100% rename from en/04_Redactor/01_v2.x/08_Uploadcare.md rename to en/04_Redactor/98_v2.x/08_Uploadcare.md diff --git a/en/04_Redactor/01_v2.x/09_Clips.md b/en/04_Redactor/98_v2.x/09_Clips.md similarity index 99% rename from en/04_Redactor/01_v2.x/09_Clips.md rename to en/04_Redactor/98_v2.x/09_Clips.md index 7be35f86..785943e5 100755 --- a/en/04_Redactor/01_v2.x/09_Clips.md +++ b/en/04_Redactor/98_v2.x/09_Clips.md @@ -13,7 +13,7 @@ Aside from the `title` and `clip` element, you can also specify a `tag` element ```` [{ "title":"Buy Button", - "clip":"Buy this product now." + "clip":"Buy this product now." },{ "title":"Copyright", "clip":"©2013 modmore." diff --git a/en/04_Redactor/01_v2.x/10_Predefined_Links.md b/en/04_Redactor/98_v2.x/10_Predefined_Links.md similarity index 100% rename from en/04_Redactor/01_v2.x/10_Predefined_Links.md rename to en/04_Redactor/98_v2.x/10_Predefined_Links.md diff --git a/en/04_Redactor/01_v2.x/90_Undo_Redo_Plugin.md b/en/04_Redactor/98_v2.x/90_Undo_Redo_Plugin.md similarity index 100% rename from en/04_Redactor/01_v2.x/90_Undo_Redo_Plugin.md rename to en/04_Redactor/98_v2.x/90_Undo_Redo_Plugin.md diff --git a/en/04_Redactor/98_v2.x/index.md b/en/04_Redactor/98_v2.x/index.md new file mode 100644 index 00000000..dbf84907 --- /dev/null +++ b/en/04_Redactor/98_v2.x/index.md @@ -0,0 +1,11 @@ +--- +title: Redactor 2.x +description: Documentation for Redactor (version 2), a premium extra from modmore for MODX. +--- + +[Redactor](https://modmore.com/redactor/) is a beautiful, user friendly, and configurable rich text editor for MODX with powerful media management. + +# Recommended Reading + +- [Configuration](Configure_Redactor) +- [Managing Media](Managing_Media) diff --git a/en/04_Redactor/99_v1.x/01_Installation.md b/en/04_Redactor/99_v1.x/01_Installation.md index 69cd4b4e..1598ba26 100644 --- a/en/04_Redactor/99_v1.x/01_Installation.md +++ b/en/04_Redactor/99_v1.x/01_Installation.md @@ -1,19 +1,19 @@ -The page you're currently looking at contains information related to Redactor 1.x. Please visit [Installation](https://www.modmore.com/redactor/documentation/installation/) for the relevant information for Redactor 2.x. +The page you're currently looking at contains information related to Redactor 1.x. Please visit [Installation](https://modmore.com/redactor/documentation/installation/) for the relevant information for Redactor 2.x. --- -Installing [Redactor](https://www.modmore.com/extras/redactor/) is no different than installing any other package from mod**more**. +Installing [Redactor](https://modmore.com/extras/redactor/) is no different than installing any other package from mod**more**. - Purchase a site license by clicking "Buy Now" above. -- Connect your MODX website to our [Package Provider](https://www.modmore.com/about/package-provider/) with an [API Key](https://www.modmore.com/account/api-keys/) -- Open Package Management and browse to _Your mod**more** account_ » _Available Purchases_. You should see Redactor in the list. (If not, check [your purchases](https://www.modmore.com/account/purchases/) and make sure the [invoice is marked completed](https://www.modmore.com/account/billing/invoices/), and contact [contact support](https://support.modmore.com/) if it still wont show up.) +- Connect your MODX website to our [Package Provider](https://modmore.com/about/package-provider/) with an [API Key](https://modmore.com/account/api-keys/) +- Open Package Management and browse to _Your mod**more** account_ » _Available Purchases_. You should see Redactor in the list. (If not, check [your purchases](https://modmore.com/account/purchases/) and make sure the [invoice is marked completed](https://modmore.com/account/billing/invoices/), and contact [contact support](https://support.modmore.com/) if it still wont show up.) - Click the Download button and wait for the package to be downloaded to your website. This usually takes between 5-15 seconds. - Close the Package Browser and find Redactor in the list of packages. Click the Install button and follow the instructions. -After a succesful installation, Redactor will be set as the default Rich Text Editor, and it will replace the content field with the Redactor editor, while enhance richtext template variables as well. You can customize behavior and looks of the editor with the many [Redactor configuration options](https://www.modmore.com/extras/redactor/documentation/configuration/), available via _System_ » _System Settings_ » _Redactor_ (in the "Namespace" dropdown, the one that defaults to "core"). +After a succesful installation, Redactor will be set as the default Rich Text Editor, and it will replace the content field with the Redactor editor, while enhance richtext template variables as well. You can customize behavior and looks of the editor with the many [Redactor configuration options](https://modmore.com/extras/redactor/documentation/configuration/), available via _System_ » _System Settings_ » _Redactor_ (in the "Namespace" dropdown, the one that defaults to "core"). -![](https://www.modmore.com/assets/uploads/2013/redactor_screen.JPG) +![](https://modmore.com/assets/uploads/2013/redactor_screen.JPG) -You can also [create new Redactor Template Variables](https://www.modmore.com/extras/redactor/documentation/template-variable/) which are richtext Template Variables, but also offer you many of the Redactor configuration options on the TV level, offering super fine control over what the editor can do. +You can also [create new Redactor Template Variables](https://modmore.com/extras/redactor/documentation/template-variable/) which are richtext Template Variables, but also offer you many of the Redactor configuration options on the TV level, offering super fine control over what the editor can do. If at any point you get stuck installing Redactor, be sure to [contact support](https://support.modmore.com/). We'd be glad to help. diff --git a/en/04_Redactor/99_v1.x/02_Configuration.md b/en/04_Redactor/99_v1.x/02_Configuration.md index 0fa7b452..5fc44c0c 100644 --- a/en/04_Redactor/99_v1.x/02_Configuration.md +++ b/en/04_Redactor/99_v1.x/02_Configuration.md @@ -1,12 +1,12 @@ -The page you're currently looking at contains information related to Redactor 1.x. Please visit [Configure Redactor](https://www.modmore.com/redactor/documentation/configuration/) for the relevant information for Redactor 2.x. +The page you're currently looking at contains information related to Redactor 1.x. Please visit [Configure Redactor](https://modmore.com/redactor/documentation/configuration/) for the relevant information for Redactor 2.x. --- Redactor comes with a whole bunch of configuration options, so you can customize the look of the editor, the available functionality and some nifty tricks that Redactor offers. -These configurations are stored as System Settings, and can be found by visiting _System_ » _System Settings_ and choosing _redactor_ in the namespace dropdown (that's the one that defaults to "core"). It is also possible to create [Redactor Template Variables instances](https://www.modmore.com/extras/redactor/documentation/template-variable/), in which case you can override many of the settings for each template variable. +These configurations are stored as System Settings, and can be found by visiting _System_ » _System Settings_ and choosing _redactor_ in the namespace dropdown (that's the one that defaults to "core"). It is also possible to create [Redactor Template Variables instances](https://modmore.com/extras/redactor/documentation/template-variable/), in which case you can override many of the settings for each template variable. -+tv Options marked with a "+" in the overview, or with the blue "+tv" label below, are options that can be configured for individual [Redactor template variables](https://www.modmore.com/extras/redactor/documentation/template-variable/). ++tv Options marked with a "+" in the overview, or with the blue "+tv" label below, are options that can be configured for individual [Redactor template variables](https://modmore.com/extras/redactor/documentation/template-variable/). [TOC] @@ -98,7 +98,7 @@ When not 0, this lets you set a placeholder text for the editor if no content is **Added in 1.5.0** -This setting allows you to add a list of predefined links in "Add link" modal. [More info](https://www.modmore.com/extras/redactor/documentation/creating-predefined-links/). +This setting allows you to add a list of predefined links in "Add link" modal. [More info](https://modmore.com/extras/redactor/documentation/creating-predefined-links/). @@ -626,10 +626,10 @@ The path, relative to the root of the media source as defined by the `Media Sour - `` if available, the pagetitle of the current resource. **Added in 1.4.0** - `` if available, the alias of the current resource. **Added in 1.4.0** - `` if available, the context\_key of the current resource. **Added in 1.4.0** -- `https://www.modmore.com/` Your MODX site\_url. **Added in 1.5.0** +- `https://modmore.com/` Your MODX site\_url. **Added in 1.5.0** - `/assets/` Your MODX assets\_url. **Added in 1.5.0** -Also see `Image Upload Path`, `Media Source` and [Using Media Sources with Redactor](https://www.modmore.com/extras/redactor/documentation/media-sources/) +Also see `Image Upload Path`, `Media Source` and [Using Media Sources with Redactor](https://modmore.com/extras/redactor/documentation/media-sources/) @@ -653,10 +653,10 @@ The path, relative to the root of the media source as defined by the `Media Sour - `` if available, the pagetitle of the current resource. **Added in 1.4.0** - `` if available, the alias of the current resource. **Added in 1.4.0** - `` if available, the context\_key of the current resource. **Added in 1.4.0** -- `https://www.modmore.com/` Your MODX site\_url. **Added in 1.5.0** +- `https://modmore.com/` Your MODX site\_url. **Added in 1.5.0** - `/assets/` Your MODX assets\_url. **Added in 1.5.0** -Also see `File Upload Path`, `Media Source` and [Using Media Sources with Redactor](https://www.modmore.com/extras/redactor/documentation/media-sources/) +Also see `File Upload Path`, `Media Source` and [Using Media Sources with Redactor](https://modmore.com/extras/redactor/documentation/media-sources/) @@ -769,7 +769,7 @@ Default: yes Choose (or provide the ID of) a Media Source to use for uploading and browsing images and files. This can be any type of Media Source that implements uploading and browsing of images. -Also see `File Upload Path`, `Image Upload Path` and [Using Media Sources with Redactor](https://www.modmore.com/extras/redactor/documentation/media-sources/) +Also see `File Upload Path`, `Image Upload Path` and [Using Media Sources with Redactor](https://modmore.com/extras/redactor/documentation/media-sources/) diff --git a/en/04_Redactor/99_v1.x/06_Creating_Custom_Formats.md b/en/04_Redactor/99_v1.x/06_Creating_Custom_Formats.md index 0475a355..b438dde4 100644 --- a/en/04_Redactor/99_v1.x/06_Creating_Custom_Formats.md +++ b/en/04_Redactor/99_v1.x/06_Creating_Custom_Formats.md @@ -1,10 +1,10 @@ -The page you're currently looking at contains information related to Redactor 1.x. Please visit [Custom Formatting](https://www.modmore.com/redactor/documentation/custom-formats/) for the relevant information for Redactor 2.x. +The page you're currently looking at contains information related to Redactor 1.x. Please visit [Custom Formatting](https://modmore.com/redactor/documentation/custom-formats/) for the relevant information for Redactor 2.x. For Redactor 1.2.0, we added something special to do exactly what many of you requested, custom formatting. By making use of the [Redactor Styles Plugin](https://github.com/jpdevries/styles) by JP DeVries, you can create custom formats to more easily format your text. [Redactor TVs](Custom_Template_Variable) can even have their own custom formats that overrides the System Defaults. -![Using className to style individiual format options in the toolbar](https://www.modmore.com/assets/uploads/redactor_custom_styles.png "Styling individual Format Options") +![Using className to style individiual format options in the toolbar](https://modmore.com/assets/uploads/redactor_custom_styles.png "Styling individual Format Options") To add custom styles to Redactor you will need to set the [redactor.stylesJson](Configuration) System Setting to properly formatted JSON that defines each of your styles. diff --git a/en/04_Redactor/99_v1.x/07_Using_Clips_Plugin.md b/en/04_Redactor/99_v1.x/07_Using_Clips_Plugin.md index 697d7bae..3264c0ea 100644 --- a/en/04_Redactor/99_v1.x/07_Using_Clips_Plugin.md +++ b/en/04_Redactor/99_v1.x/07_Using_Clips_Plugin.md @@ -11,7 +11,7 @@ Below you will find several preconfigured examples, but you can create your own ```` [{ "title":"Buy Button", - "clip":"Buy this product now." + "clip":"Buy this product now." },{ "title":"Copyright", "clip":"©2013 modmore." diff --git a/en/04_Redactor/99_v1.x/08_Custom_Component_Usage.md b/en/04_Redactor/99_v1.x/08_Custom_Component_Usage.md index 49868995..843ab645 100644 --- a/en/04_Redactor/99_v1.x/08_Custom_Component_Usage.md +++ b/en/04_Redactor/99_v1.x/08_Custom_Component_Usage.md @@ -97,7 +97,7 @@ Let us know if your Extra supports Redactor too, and we'll gladly add it to the ## Version Detection -One of the [several improvements in Redactor 1.5](https://www.modmore.com/blog/2014/announcing-redactor-1.5/) introduced the ability to check the current version of Redactor through our API. We do **not** recommend using version detection, however if you absolutely must it is possible through `$redactor->version`. +One of the [several improvements in Redactor 1.5](https://modmore.com/blog/2014/announcing-redactor-1.5/) introduced the ability to check the current version of Redactor through our API. We do **not** recommend using version detection, however if you absolutely must it is possible through `$redactor->version`. ```` php diff --git a/en/04_Redactor/99_v1.x/09_Predefined_Links.md b/en/04_Redactor/99_v1.x/09_Predefined_Links.md index 678cd366..62b9f4ce 100644 --- a/en/04_Redactor/99_v1.x/09_Predefined_Links.md +++ b/en/04_Redactor/99_v1.x/09_Predefined_Links.md @@ -2,11 +2,11 @@ The page you're currently looking at contains information related to Redactor 1. --- -One of the many additions to [Redactor 1.5](https://www.modmore.com/blog/2014/announcing-redactor-1.5/) is the ability to quickly choose from predefined links in the edit link modal window. By authoring a list of links to be available Redactor will add a select box so your most important links are only two clicks away. +One of the many additions to [Redactor 1.5](https://modmore.com/blog/2014/announcing-redactor-1.5/) is the ability to quickly choose from predefined links in the edit link modal window. By authoring a list of links to be available Redactor will add a select box so your most important links are only two clicks away. ![Predefined Links make for quicker editing in Redactor 1.5](http://assets.modmore.com/img/blog/redactor_link.png) -To use Predefined Links, you'll need to create a JSON object for Redactor to reference, and set the [Predefined Links Setting](https://www.modmore.com/extras/redactor/documentation/configuration/#predefined+links) to a URL that serves your JSON. +To use Predefined Links, you'll need to create a JSON object for Redactor to reference, and set the [Predefined Links Setting](https://modmore.com/extras/redactor/documentation/configuration/#predefined+links) to a URL that serves your JSON. ```` javascript diff --git a/en/04_Redactor/99_v1.x/10_Customising_the_Toolbar.md b/en/04_Redactor/99_v1.x/10_Customising_the_Toolbar.md index 92304006..c6335dec 100644 --- a/en/04_Redactor/99_v1.x/10_Customising_the_Toolbar.md +++ b/en/04_Redactor/99_v1.x/10_Customising_the_Toolbar.md @@ -1,4 +1,4 @@ -The page you're currently looking at contains information related to Redactor 1.x. Please visit [Custom Toolbars](https://www.modmore.com/redactor/documentation/customising-the-editor/) for the relevant information for Redactor 2.x. +The page you're currently looking at contains information related to Redactor 1.x. Please visit [Custom Toolbars](https://modmore.com/redactor/documentation/customising-the-editor/) for the relevant information for Redactor 2.x. @@ -13,7 +13,7 @@ With a little bit of CSS, or as we like to call it [Sass](http://sass-lang.com) ### Sass -Here’s a look at the source Sass we use to pre-process our [CSS below](https://www.modmore.com/extras/redactor/documentation/customizing-the-toolbar/#css). +Here’s a look at the source Sass we use to pre-process our [CSS below](https://modmore.com/extras/redactor/documentation/customizing-the-toolbar/#css). ```` scss @@ -137,7 +137,7 @@ Changing the colors of the Sass variables in [this gist](http://sassmeister.com/ [Play with this gist on SassMeister.](https://sassmeister.com/gist/17f1a62335428a48a7ac) -You’ll want to include this CSS on your MODX manager pages so that they override the default Redactor styles. You can do this by supplying the [Stylesheet Setting](https://www.modmore.com/extras/redactor/documentation/configuration/#stylesheet) with an absolute path to your custom stylesheet which may looking something like: +You’ll want to include this CSS on your MODX manager pages so that they override the default Redactor styles. You can do this by supplying the [Stylesheet Setting](https://modmore.com/extras/redactor/documentation/configuration/#stylesheet) with an absolute path to your custom stylesheet which may looking something like: ```` html [[++asset_url]]css/redactor-custom.css diff --git a/en/04_Redactor/99_v1.x/index.md b/en/04_Redactor/99_v1.x/index.md index 5ae48028..9820191a 100644 --- a/en/04_Redactor/99_v1.x/index.md +++ b/en/04_Redactor/99_v1.x/index.md @@ -4,6 +4,6 @@ description: Legacy documentation for Redactor for MODX v1. --- -Redactor 1.x was our original implementation of Redactor. In September 2015 we released [Redactor 2.0](https://www.modmore.com/blog/2015/announcing-redactor-2.0/) as a free upgrade. Redactor 1 is no longer officially supported following the release of Redactor 2. [The latest Redactor documentation can be found here](../../Redactor). +Redactor 1.x was our original implementation of Redactor. In September 2015 we released [Redactor 2.0](https://modmore.com/blog/2015/announcing-redactor-2.0/) as a free upgrade. Redactor 1 is no longer officially supported following the release of Redactor 2. [The latest Redactor documentation can be found here](../../Redactor). The Redactor 1.x documentation is archived in this section. [Check our notes when upgrading from Redactor 1.x to 2.0](../v2.x/Upgrading_from_Redactor_1.x_to_2.0) diff --git a/en/05_SimpleCart/images/authnet-clientkey.jpg b/en/05_SimpleCart/images/authnet-clientkey.jpg new file mode 100644 index 00000000..87d70cca Binary files /dev/null and b/en/05_SimpleCart/images/authnet-clientkey.jpg differ diff --git a/en/05_SimpleCart/images/authnet-configuration.jpg b/en/05_SimpleCart/images/authnet-configuration.jpg new file mode 100644 index 00000000..2fa29b12 Binary files /dev/null and b/en/05_SimpleCart/images/authnet-configuration.jpg differ diff --git a/en/05_SimpleCart/images/authnet-form.jpg b/en/05_SimpleCart/images/authnet-form.jpg new file mode 100644 index 00000000..6487420a Binary files /dev/null and b/en/05_SimpleCart/images/authnet-form.jpg differ diff --git a/en/05_SimpleCart/v2.x/01_Frontend/01_Categories/02_Template_Setup.md b/en/05_SimpleCart/v2.x/01_Frontend/01_Categories/02_Template_Setup.md index 44c93427..82444adc 100644 --- a/en/05_SimpleCart/v2.x/01_Frontend/01_Categories/02_Template_Setup.md +++ b/en/05_SimpleCart/v2.x/01_Frontend/01_Categories/02_Template_Setup.md @@ -87,10 +87,10 @@ The SimpleCart meta fields contain the image, price, code and stock. - `[[+product_price_formatted]]`: the product price for one item, formatted with the currency sign and decimal/thousands separator. - `[[+product_code]]`: the product code or SKU for the product - `[[+product_stock]]`: the number of items still in stock for this product -- `[[+special_price]]`: (since v2.5) the special discounted price for the product, unformatted. -- `[[+special_price_formatted]]`: (since v2.5) a properly formatted representation of the special product price. -- `[[+special_valid_from]]`: (since v2.5) the start date for when the special price becomes/became valid, as a datetime string. -- `[[+special_valid_to]]`: (since v2.5) the end date for the special price, as a datetime string. +- `[[+product_special_price]]`: (since v2.5) the special discounted price for the product, unformatted. +- `[[+product_special_price_formatted]]`: (since v2.5) a properly formatted representation of the special product price. +- `[[+product_special_valid_from]]`: (since v2.5) the start date for when the special price becomes/became valid, as a datetime string. +- `[[+product_special_valid_to]]`: (since v2.5) the end date for the special price, as a datetime string. For tax/VAT prices there are a number of other placeholders, however it is important to note that these only contain the right values if SimpleCart can figure out which prices to use. This means that if your Tax Rate has rules based on the country for example, that SimpleCart will **not** apply that tax rate until it knows what country a user is from. diff --git a/en/05_SimpleCart/v2.x/01_Frontend/04_Checkout/01_Order_and_Delivery_Addresses.md b/en/05_SimpleCart/v2.x/01_Frontend/04_Checkout/01_Order_and_Delivery_Addresses.md index 595aebed..262e9456 100644 --- a/en/05_SimpleCart/v2.x/01_Frontend/04_Checkout/01_Order_and_Delivery_Addresses.md +++ b/en/05_SimpleCart/v2.x/01_Frontend/04_Checkout/01_Order_and_Delivery_Addresses.md @@ -31,7 +31,7 @@ The mapping key for the delivery address is done the same way, but with `&delive [[!FormIt? ... &orderAddress=`address1:street,address2:number` - &deliverAddress=`firstname:delivery_firstname,lastname:delivery_lastname,address1:delivery_street,address2:delivery_number,...` + &deliveryAddress=`firstname:delivery_firstname,lastname:delivery_lastname,address1:delivery_street,address2:delivery_number,...` ... ]] ```` diff --git a/en/05_SimpleCart/v2.x/01_Frontend/04_Checkout/03_Confirmation_Page.md b/en/05_SimpleCart/v2.x/01_Frontend/04_Checkout/03_Confirmation_Page.md index 67237443..8b6ccf4c 100644 --- a/en/05_SimpleCart/v2.x/01_Frontend/04_Checkout/03_Confirmation_Page.md +++ b/en/05_SimpleCart/v2.x/01_Frontend/04_Checkout/03_Confirmation_Page.md @@ -36,7 +36,7 @@ Finally, if you didn't have it yet, make sure the redirect hook is set and that On the confirmation page you'll need to load the information from the checkout page with the FormItRetriever snippet, and add all that information to hidden input fields inside the form. You'll also need a FormIt call with the scCreateOrder hook which will send the user to the desired payment gateway, and/oor the thank you page. -Basically you're creating a [one-page checkout](https://www.modmore.com/simplecart/documentation/tutorials/one-page-checkout/) here, by collecting all information and then sending it to SimpleCart in one sweep. +Basically you're creating a [one-page checkout](https://modmore.com/simplecart/documentation/tutorials/one-page-checkout/) here, by collecting all information and then sending it to SimpleCart in one sweep. Here's an example of what the confirmation page might look like. diff --git a/en/05_SimpleCart/v2.x/02_Manager/00_Orders/index.md b/en/05_SimpleCart/v2.x/02_Manager/00_Orders/index.md index 7c21b39a..efdcd747 100644 --- a/en/05_SimpleCart/v2.x/02_Manager/00_Orders/index.md +++ b/en/05_SimpleCart/v2.x/02_Manager/00_Orders/index.md @@ -37,6 +37,6 @@ To view the order details you can right click on an order in the list and choose ## Creating a new order -With the _Create new order_ button you can create an order from the back-end. This is useful for invoice-based billing or when accepting orders via the phone. [Read more about creating orders here](https://www.modmore.com/simplecart/documentation/manager/orders/create-new-order/). +With the _Create new order_ button you can create an order from the back-end. This is useful for invoice-based billing or when accepting orders via the phone. [Read more about creating orders here](https://modmore.com/simplecart/documentation/manager/orders/create-new-order/). [ ![The SimpleCart order create window](https://assets.modmore.com/uploads/2015/12/orders_overview_createorder.png)](https://assets.modmore.com/uploads/2015/12/orders_overview_createorder.png "The SimpleCart order create window") \ No newline at end of file diff --git a/en/05_SimpleCart/v2.x/02_Manager/05_Administration/01_Order_Statuses.md b/en/05_SimpleCart/v2.x/02_Manager/05_Administration/01_Order_Statuses.md index 6cdce024..7cb9b228 100644 --- a/en/05_SimpleCart/v2.x/02_Manager/05_Administration/01_Order_Statuses.md +++ b/en/05_SimpleCart/v2.x/02_Manager/05_Administration/01_Order_Statuses.md @@ -21,7 +21,7 @@ The name a **unique reference** for the status. It should be unique, lowercase, The title is what the status is shown as. This is stored as a lexicon (you can switch the language to see translations) and can change. -Every status can also have a default message. This is meant to be the default message that is sent to the customer when the order status is updated. By filling in a default message, it will appear automatically [when changing the order status](https://www.modmore.com/simplecart/documentation/manager/orders/update-status/). +Every status can also have a default message. This is meant to be the default message that is sent to the customer when the order status is updated. By filling in a default message, it will appear automatically [when changing the order status](https://modmore.com/simplecart/documentation/manager/orders/update-status/). This default message can also contain placeholders like `[[+firstname]]` and `[[+lastname]]`. diff --git a/en/05_SimpleCart/v2.x/03_Snippets/07_scFinishOrder.md b/en/05_SimpleCart/v2.x/03_Snippets/07_scFinishOrder.md index f901db67..633be5dc 100644 --- a/en/05_SimpleCart/v2.x/03_Snippets/07_scFinishOrder.md +++ b/en/05_SimpleCart/v2.x/03_Snippets/07_scFinishOrder.md @@ -38,6 +38,10 @@ Name of a chunk, or `@INLINE:` or `@FILE:` prefixed value that's used as an inli Name of a chunk, or `@INLINE:` or `@FILE:` prefixed value that's used as an inline chunk, or file that's loaded. This will be shown when the order was created and paid properly. [Read more](../Frontend/Checkout/Thank_You). +### orderPending + +Name of a chunk, or `@INLINE:` or `@FILE:` prefixed value for an inline chunk or file, which will be shown when an asynchronous payment is still pending confirmation. Defaults to the `scFinishOrderPending` chunk, which automatically refreshes the page every 5 seconds. + ### placeholderPrefix Default: `order.` diff --git a/en/05_SimpleCart/v2.x/03_Snippets/10_scGetOrders.md b/en/05_SimpleCart/v2.x/03_Snippets/10_scGetOrders.md index 2f4ea36c..c5328734 100644 --- a/en/05_SimpleCart/v2.x/03_Snippets/10_scGetOrders.md +++ b/en/05_SimpleCart/v2.x/03_Snippets/10_scGetOrders.md @@ -18,6 +18,12 @@ Default: [scOrders](../Chunks/scOrders) Name of the chunk to wrap the order list. +### loginTpl + +Default: [scOrdersLogin](../Chunks/scOrdersLogin) + +Name of the chunk to show when the user is not currently logged in. + ### rowTpl Default: [scOrdersRow](../Chunks/scOrdersRow) diff --git a/en/05_SimpleCart/v2.x/04_Chunks/24_scOrdersLogin.md b/en/05_SimpleCart/v2.x/04_Chunks/24_scOrdersLogin.md new file mode 100644 index 00000000..b7a011c3 --- /dev/null +++ b/en/05_SimpleCart/v2.x/04_Chunks/24_scOrdersLogin.md @@ -0,0 +1,11 @@ +The scOrdersLogin chunk is used by the [scGetOrders Snippet](../Snippets/scGetOrders) to show a message when the user is not logged in. + +This chunk was added in 2.5.2. + +## Default scOrdersLogin chunk + +```` html + +```` \ No newline at end of file diff --git a/en/05_SimpleCart/v2.x/05_Payment_Methods/00_PayPal.md b/en/05_SimpleCart/v2.x/05_Payment_Methods/00_PayPal.md index e271a23f..351e8554 100644 --- a/en/05_SimpleCart/v2.x/05_Payment_Methods/00_PayPal.md +++ b/en/05_SimpleCart/v2.x/05_Payment_Methods/00_PayPal.md @@ -29,14 +29,20 @@ The name cannot be changed, as that is tied in with loading and identifying the ## Getting Live API Keys -To get your Live API Keys, login to the PayPal dashboard. Go to Tools in the top menu, and choose PayPal Express Checkout under Accept Payments Anywhere. +> Note: PayPal tends to shuffle around their menus from time to time. [Here's the official guidance for creating the relevant credentials.](https://developer.paypal.com/docs/nvp-soap-api/apiCredentials/#api-signatures) - [ ![](https://assets.modmore.com/uploads/2015/06/Screen_Shot_2015_06_11_at_17.30.33.png)](https://assets.modmore.com/uploads/2015/06/Screen_Shot_2015_06_11_at_17.30.33.png) +To get your Live API Keys, login to the PayPal dashboard. Hover your name in the top right and choose **Account Settings**. Under **Account Access** click on update for the **API Access** entry. -Under Integrated Carts, find the link that says Request API Signature and follow the instructions until you get the API Username, Password and Signature. Enter those values into the gateway configuration to set up your cart. +Find the **NVP/SOAP API integration (Classic)** item under Custom checkout experience and click **Manage API credentials**. + +![Finding API Credentials](https://docs.modmore.com/en/Commerce/images/gateways/paypal-nvp.jpg) + +Generate the API Signature and copy the username, password, and signature into the payment method. ## Getting Sandbox API Keys -Login to the [PayPal Developer Site](https://developer.paypal.com/developer/accounts/), and browse to Sandbox > Accounts. Create a new account with type Business (Merchant Account). In the list of accounts, expand the merchant account and click on Profile. In the modal window, you can find the Username, Password and Signature on the _API Credentials_ tab. +Login to the [PayPal Developer Site](https://developer.paypal.com/developer/accounts/), and browse to Sandbox > Accounts. + +Create a new account with type Business (Merchant Account). In the list of accounts, expand the merchant account and click on Profile. In the modal window, you can find the Username, Password and Signature on the API Credentials tab. -![PayPal Sandbox](../../images/paypal-sandbox.jpg) +![PayPal Sandbox Credentials](https://docs.modmore.com/en/SimpleCart/images/paypal-sandbox.jpg) diff --git a/en/05_SimpleCart/v2.x/05_Payment_Methods/01_Mollie.md b/en/05_SimpleCart/v2.x/05_Payment_Methods/01_Mollie.md index 6b539c99..7a6af287 100644 --- a/en/05_SimpleCart/v2.x/05_Payment_Methods/01_Mollie.md +++ b/en/05_SimpleCart/v2.x/05_Payment_Methods/01_Mollie.md @@ -21,3 +21,11 @@ To manage the title, description and transaction fee for the Mollie gateway, you The name cannot be changed, as that is tied in with loading and identifying the gateway. [ ![](https://assets.modmore.com/uploads/2015/06/Screen_Shot_2015_06_11_at_17.25.37.png)](https://assets.modmore.com/uploads/2015/06/Screen_Shot_2015_06_11_at_17.25.37.png) + +## Payments not getting confirmed? + +The Mollie integration uses a webhook to listen to payments. If you're constantly stuck in the "Payment is awaiting confirmation" view, the webhook may be failing. + +To check the webhook URL, login to the Mollie dashboard and look at a specific transaction. Find the Webhook URL for the transaction, and verify that it is correct. + +In many cases, we've seen that webhook URLs are generated with `HTTP` while the site runs on `HTTPS`. That can cause webhooks to fail. To fix that, update the `server_protocol` system setting in MODX to `https`. diff --git a/en/05_SimpleCart/v2.x/05_Payment_Methods/02_StripeV2.md b/en/05_SimpleCart/v2.x/05_Payment_Methods/02_StripeV2.md index f1016bcc..205a813b 100644 --- a/en/05_SimpleCart/v2.x/05_Payment_Methods/02_StripeV2.md +++ b/en/05_SimpleCart/v2.x/05_Payment_Methods/02_StripeV2.md @@ -18,8 +18,8 @@ Compared to version 1, version 2 of the gateways require a bit more set up. This Here's what you need to do. -1. First, install the package from the modmore.com [package provider](https://www.modmore.com/about/package-provider/). -2. [Create a webhook in the Stripe dashboard](https://dashboard.stripe.com/account/webhooks), pointing it to `https://yoursite.com/assets/components/simplecart_stripe/connector.php?action=webhook`. +1. First, install the package from the modmore.com [package provider](https://modmore.com/about/package-provider/). +2. [Create a webhook in the Stripe dashboard](https://dashboard.stripe.com/account/webhooks), pointing it to `https://yoursite.com/assets/components/simplecart_stripe/connector.php?action=webhook` Select the events `source.charged`, `source.failed` and `source.cancelled`. 3. Open the webhook in the dashboard, and copy the *Signing Secret* into the `simplecart_stripe.webhook_secret` system setting, located under the `simplecart_stripe` namespace. 4. Back in the Stripe Dashboard in the API > Webhooks section, click on your endpoint. Test the webhook by clicking the `Send test webhook` button in the top right corner. Leave it on the default event type, and click on _Send test webhook_ button. Make sure the response looks like JSON, and has a message of `Unsupported event type, ignoring request`. If you get a different response, that means you might not have copied the webhook secret properly, and you wont be able of accepting payments. 5. Head back to the Payment Methods tab in the SimpleCart > Administer component. Click the cog icon next to each of the gateways and make sure that the _Secret Key_ is filled with your [Stripe Secret Key](https://dashboard.stripe.com/account/apikeys). @@ -56,4 +56,4 @@ To manage the title, description and transaction fee for the gateways, you right The name cannot be changed, as that is tied in with loading and identifying the gateway. -[ ![](https://assets.modmore.com/uploads/2015/06/stripeupdate.png)](https://assets.modmore.com/uploads/2015/06/stripeupdate.png) \ No newline at end of file +[ ![](https://assets.modmore.com/uploads/2015/06/stripeupdate.png)](https://assets.modmore.com/uploads/2015/06/stripeupdate.png) diff --git a/en/05_SimpleCart/v2.x/05_Payment_Methods/03_Authorize.net.md b/en/05_SimpleCart/v2.x/05_Payment_Methods/03_Authorize.net.md index f1de76fc..b5ff63b0 100644 --- a/en/05_SimpleCart/v2.x/05_Payment_Methods/03_Authorize.net.md +++ b/en/05_SimpleCart/v2.x/05_Payment_Methods/03_Authorize.net.md @@ -1,38 +1,60 @@ -The Authorize.net Gateway for SimpleCart is free to install from the modmore.com package provider. Its source code can be found on [GitHub](https://github.com/modmore/SimpleCart_Stripe) and development was sponsored by Roger Sullivan, Founder of [Snow Day Code](http://snowdaycode.com/). Thanks, Roger! +The Authorize.net Gateway for SimpleCart is free to install from the modmore.com package provider. Its source code can be found on [GitHub](https://github.com/modmore/SimpleCart_Authorize.Net) and development was sponsored by Roger Sullivan, Founder of [Snow Day Code](http://snowdaycode.com/). Thanks, Roger! After installing the gateway, it will show up in the Payment Methods tab in the SimpleCart > Administer component. - [ ![](https://assets.modmore.com/uploads/2015/06/stripegateway.png)](https://assets.modmore.com/uploads/2015/06/stripegateway.png) +> **Important: version 1.x of the gateway stopped working in July 2019. You should upgrade to version 2 if you haven't yet.** + +[TOC] + +## Upgrading from v1.x + +In v1.x of the gateway, the customer was redirected off-site to a hosted payment page ("SIM" integration). In v2, the customer stays on-site and enters their credit card information on the payment page ("Accept.js" integration). + +v1 of the gateway is no longer functional due to the MD5 hash deprecation. + +If you're upgrading from v1, you'll need to update your payment gateway configuration to accept payments. + +Most importantly, you'll need to enter the **Client Key**. Find it in your Authorize.net dashboard under Account > Settings > Security Settings > General Security Settings > Manage Client Key. + +![Finding your Client Key](../../images/authnet-clientkey.jpg) + +Copy the client key, go to Extras > SimpleCart > Administer and click on the cog icon for the Authorize.net gateway. Enter the client key in the appropriate property there. + +You'll also want to make sure the design meets your needs. A basic design is included in the standard SimpleCart CSS, but you can customise it as detailed below. ## Managing Gateway Configuration To manage the properties for Authorize.net, simply hit the Cog icon next to the name, or right click the row in the grid and choose Configuration. - [ ![](https://assets.modmore.com/uploads/2015/08/sc_authnet_conf.png)](https://assets.modmore.com/uploads/2015/08/sc_authnet_conf.png) +![Managing Authorize.net configuration](../../images/authnet-configuration.jpg) Here's what each of the properties are for: -- MD5 Hash Secret: the MD5 Hash Secret is really important, as this is used to validate the response from Authorize.net to make sure it is the real deal. The Hash Secret is a string of **up to 20 characters long**, which you also need to add to your Authorize.net merchant account. You can find this under Account > Security Settings > General Security Settings > MD5-Hash. -- Login ID: the ID for your merchant account (or sandbox account). This is provided during signup, but can also be found under Account > Security Settings > General Security Settings > API Login ID and Transaction Key. -- Transaction Key: found at the same place as the Login ID, the Transaction Key is also used for authentication and validation of the MD5 signature. -- Test Mode: set to 1 to use the sandbox, or 0 to use the live Authorize.net environment. +- **Client Key**: the public key, used for the front-end Accept.js implementation. Find it in the Authorize.net Merchant Dashboard (or Sandbox) at Account > Settings > Security Settings > General Security Settings > Manage Public Client Key. +- **Currency**: the 3-character code for the currency you're using. This should match your SimpleCart configuration. +- **Form Chunk**: name of the chunk to use for rendering the client-side payment form. See the section on customisation below. +- **Login ID**: the ID for your merchant account (or sandbox account). This is provided during signup, and can also be found under Account > Security Settings > General Security Settings > API Credentials & Keys. +- **Test Mode**: set to 1 to use the sandbox, or 0 to use the live Authorize.net environment. (Note: transactions do no show up in the sandbox currently, because the payments are marked as being test requests.) +- **Transaction Key**: found at the same place as the Login ID, the Transaction Key is used for server-side authentication and validation. ## Changing the Title, Description and Price -To manage the title, description and transaction fee for the Stripe gateway, you right click the gateway in the list and choose _Update Method_. In the popup, you can then edit those values. +To manage the title, description and transaction fee for the Authorize.net gateway, you right click the gateway in the list and choose _Update Method_. In the popup, you can then edit those values. + +The name cannot be changed, as that is tied in with loading and identifying the gateway. The title is what is shown to the customer in the checkout. -The name cannot be changed, as that is tied in with loading and identifying the gateway. +These values are persisted to the lexicon. On the top-right of the payment methods grid, you can choose the language. Select the language before opening the method update window. - [ ![](https://assets.modmore.com/uploads/2015/08/sc_authnet_method.png)](https://assets.modmore.com/uploads/2015/08/sc_authnet_method.png) +[ ![](https://assets.modmore.com/uploads/2015/08/sc_authnet_method.png)](https://assets.modmore.com/uploads/2015/08/sc_authnet_method.png) -## Streamlining the Hosted Checkout Form +## Customising the payment form -As SimpleCart has already collected billing (and optional shipping) addresses before the user is forwarded to Authorize.net, we can simplify the hosted checkout form significantly. To do this, login to the sandbox/merchant dashboard again, and go to Account > Transaction Format Settings > Transaction Submission Settings > Payment Form. +If you're looking to make the payment form prettier, you can get quite far just by implementing your own CSS. It's recommended to use the browser development tools to inspect the exact markup, available classes, and current style inheritance to identify how to best approach your tweaks. -In the page that opens you have several options for customising the checkout. You will likely want to use the Color & Font Settings, Header and Footer options for making the checkout look similar to your site visually, but right now we're interested in Form Fields primarily. +SimpleCart v2.6.2+ includes generic styling for the payment form that should make it look at least decent if you enable the default CSS. -When opening the Form Fields page you will see a lot of checkboxes. You can choose to hide all of the fields completely by unticking them all, but as the gateway passes client information to Authorize.net you can also choose to leave "View" checked for the majority of the fields. That way the information is shown again on the checkout form for verification of the user. +![Example Authorize.net payment form using the default styles.](../../images/authnet-form.jpg) -_Please note that if you do choose to leave the various fields editable that the submitted information is NOT updated in SimpleCart when the user returns to the site._ +If you want to go beyond just styling, you can also set a custom **Form Chunk** in the gateway properties. Set it to the name of a new chunk, that you base off the default `scAuthorizeNetForm` chunk. The `scAuthorizeNetForm` chunk is overwritten on upgrade and should not be edited directly. -After the user enters their credit card number and submits the form, they will be sent back to the Thank You page of your shop where the payment is validated and the order gets processed. \ No newline at end of file +Note that if you go this route, you should make sure with every update of the gateway that it still works as expected. In rare cases, you may need to incorporate some changes into your own chunk. diff --git a/en/05_SimpleCart/v2.x/index.md b/en/05_SimpleCart/v2.x/index.md index fce7b728..ab3a1f52 100644 --- a/en/05_SimpleCart/v2.x/index.md +++ b/en/05_SimpleCart/v2.x/index.md @@ -1,9 +1,9 @@ --- -title: SimpleCart -description: Documentation for SimpleCart, a premium webshop extra from modmore for MODX. +title: SimpleCart 2.x +description: Documentation for SimpleCart, a premium webshop extra from modmore for MODX. --- -[SimpleCart](https://www.modmore.com/simplecart/) is an easy to use e-commerce solution with online payments, coupons and more for your MODX site. +[SimpleCart](https://modmore.com/simplecart/) is an easy to use e-commerce solution with online payments, coupons and more for your MODX site. # Recommended Reading diff --git a/en/06_BabelTranslate/v1/01_Installation.md b/en/06_BabelTranslate/v1/01_Installation.md new file mode 100755 index 00000000..8639f976 --- /dev/null +++ b/en/06_BabelTranslate/v1/01_Installation.md @@ -0,0 +1,7 @@ +The MODX installer should install the package automatically from the modmore +repository. + +To install the extra, Babel must be installed first. + +There are some [System_Settings](03_System_Settings) available in the +_babeltranslate_ namespace. diff --git a/en/06_BabelTranslate/v1/02_Usage.md b/en/06_BabelTranslate/v1/02_Usage.md new file mode 100755 index 00000000..ce0c9051 --- /dev/null +++ b/en/06_BabelTranslate/v1/02_Usage.md @@ -0,0 +1,38 @@ +After installation, a MODX resource contains a new Translate button. This button +opens a menu for translating the resource. + +[![](img/buttons.png)](img/buttons.png) + +The first section of the menu contains (if available) all linked babel contexts +and provides a translation from the context language set with the context +setting `cultureKey`. + +The second section of the menu contains a menu entry, that shows the usage +status of the DeepL API. + +[![](img/status.png)](img/status.png) + +## Available Languages + +The source language list is created by linked Babel resources and their +`cultureKey` setting. The target language is set with the `cultureKey` setting +of the current resoures context. + +The following source and target languages are currently available: + +### Source Languages + +`bg`, `cs`, `da`, `de`, `el`, `en`, `es`, `et`, `fi`, `fr`, `hu`, `id`, `it`, +`ja`, `ko`, `lt`, `lv`, `nb`, `nl`, `pl`, `pt`, `ro`, `ru`, `sk`, `sl`, `sv`, +`tr`, `zh` + +### Target Languages + +`bg`, `cs`, `da`, `de`, `el`, `en-GB`, `en-US`, `es`, `et`, `fi`, `fr`, `hu`, +`id`, `it`, `ja`, `ko`, `lt`, `lv`, `nb`, `pl`, `pt-PT`, `pt-BR`, `ro`, `ru`, +`sk`, `sl`, `sv`, `tr`, `zh` + +If the target language has multiple dialects, the first dialect in the above +list is automatically selected. If, for example, translation to `en-US` is +required, then this can be specified in an additional context setting +`translationKey`. diff --git a/en/06_BabelTranslate/v1/03_System_Settings.md b/en/06_BabelTranslate/v1/03_System_Settings.md new file mode 100755 index 00000000..d09dfeb6 --- /dev/null +++ b/en/06_BabelTranslate/v1/03_System_Settings.md @@ -0,0 +1,38 @@ +_BabelTranslate_ contains some _system settings_ in the `babeltranslate` namespace. + +These are available in the MODX system settings panel. + +| Key | Name | Description | Default | +|---------------------------------------------|--------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------| +| babeltranslate.debug | Debug | Log debug information in MODX error log. | No | +| babeltranslate.deepl_auth_key | DeepL API Auth Key | The DeepL Auth Key to access the DeepL API. | - | +| babeltranslate.translate_duplicate | Translate Babel Duplicate | Translate the duplicate Babel resource directly. | No | +| babeltranslate.translate_resource_cb_fields | Translate ContentBlocks Fields | JSON encoded object of ContentBlocks fields that need to be translated. Each record contains the ContentBlocks field ID as a key, the value contains several options: `type` is optional (it is otherwise set by the ContentBlocks field type) and can be filled with `text`, `single` and `grid`. `nested` is optional (it is otherwise set by the ContentBlocks field type) and it can contain the key of the nested values in the ContentBlocks value. `fields` is optional (it defaults to `["value"]`) and it can be filled with an array of field names which will be translated. Example: `{"1":{"type":"text"},"8":{"type":"single","fields":["title"]},"9":{"type":"grid","nested":"images",fields":["title","description"]}}` | - | +| babeltranslate.translate_resource_fields | Translate Fields | Comma-separated list of resource fields that need to be translated. | pagetitle, longtitle, content | +| babeltranslate.translate_resource_tvs | Translate Template Variables | JSON encoded object of template variables that need to be translated. Each record contains the template variable name as a key, the value contains several options: `type` is optional (it is otherwise set by the template variable type) and can be filled with `text`, `single`, `grid` and `custom`. `fields` is optional (it defaults to `["value"]`) and it can be filled with an array of field names which will be translated. Example: `{"rte":{"type":"text"},"migx":{"type":"grid","fields":["title","description"]},"imageplus":{"type":"single","fields":["title","description"]}},"special":{"type":"custom"}}` | - | + +The settings `babeltranslate.translate_resource_fields`, +`babeltranslate.translate_resource_tvs` and +`babeltranslate.translate_resource_cb_fields` can use `@FILE` or `@CHUNK` +bindings. Path placeholders like `{core_path}`, `{base_path}` and +`{assets_path}` can be used. All paths have to stay inside the MODX base path +because of security reasons. + +## Custom template variable translation type + +The custom type of `babeltranslate.translate_resource_tvs` will be handled by a +plugin in `OnBabelTranslateCustomTV`. There exist a disabled skeleton plugin in +the BabelTranslate category. Duplicate and edit that plugin to add your own +translation handling. + +The plugin can use the following event +properties: + +| Property | Content | +|-------------|--------------------------------------------------------------------------------------------------------------------| +| translator | The translator class. Translating a string is done by `$translator->translate($string, $fromCulture, $toCulture)`. | +| resource | The current translated resource. | +| tvname | The name of the translated template variable. | +| value | The value of the translated template variable. | +| fromCulture | The culture the value is translated from. | +| toCulture | The culture the value is translated to. | diff --git a/en/06_BabelTranslate/v1/04_FAQ.md b/en/06_BabelTranslate/v1/04_FAQ.md new file mode 100755 index 00000000..add16d3d --- /dev/null +++ b/en/06_BabelTranslate/v1/04_FAQ.md @@ -0,0 +1,12 @@ +We're collecting the questions we get most often into a FAQ. If your question is +not in the list, please reach out to us via support@modmore.com and we would be +glad to help. + +[TOC] + +## What are the additional cost for the DeepL API? + +If you translate only 500.000 characters per month with BabelTranslate, you can +use the [DeepL API Free](https://www.deepl.com/en/pro/change-plan#developer). +Otherwise, you need to use the DeepL API Pro, the cost of which is flexible +based on the translated characters. diff --git a/en/06_BabelTranslate/v1/img/buttons.png b/en/06_BabelTranslate/v1/img/buttons.png new file mode 100644 index 00000000..b40cb298 Binary files /dev/null and b/en/06_BabelTranslate/v1/img/buttons.png differ diff --git a/en/06_BabelTranslate/v1/img/status.png b/en/06_BabelTranslate/v1/img/status.png new file mode 100644 index 00000000..960d565f Binary files /dev/null and b/en/06_BabelTranslate/v1/img/status.png differ diff --git a/en/06_BabelTranslate/v1/index.md b/en/06_BabelTranslate/v1/index.md new file mode 100644 index 00000000..c59172f7 --- /dev/null +++ b/en/06_BabelTranslate/v1/index.md @@ -0,0 +1,31 @@ +--- +title: BabelTranslate 1.x +description: Documentation for BabelTranslate, a translator for MODX resources. +--- + +[BabelTranslate](https://modmore.com/babeltranslate/) simple but very useful +MODX extra if you want to translate your multilingual sites with a +translation service (currently it supports DeepL API Free and Pro). + +BabelTranslate adds automatic translations to Babel. So you'll need to set up +your contexts first, configure what to translate, and then you can use the +Translate toolbar to translate the current ressource from a linked resource. +Optionally, the translation can happen automatically when Babel creates a +resource. + +BabelTranslate can translate standard content fields (pagetitle, introtext, +etc.), text and JSON-based TV types - and even ContentBlocks blocks! You +need to define what to translate in a couple of system settings. + +The volume of DeepL API Free translation is 500,000 characters per month, which +is enough for 10-100 pages (depends a lot on the length of the content). + +It is a perfect solution for users who want a well-translated content in +multilingual sites. + +# Recommended Reading + +- [Installation](01_Installation) +- [Usage](02_Usage) +- [System Settings](03_System_Settings) +- [FAQ](04_FAQ) diff --git a/en/50_Open_Source/Akismet/Akismet_Snippet.md b/en/50_Open_Source/Akismet/Akismet_Snippet.md new file mode 100644 index 00000000..0a2eab2c --- /dev/null +++ b/en/50_Open_Source/Akismet/Akismet_Snippet.md @@ -0,0 +1,111 @@ +The Akismet snippet can be used as a **hook** (in FormIt) or **preHook** (in Register and QuipReply). + +You need to instruct Akismet what fields to use. For this, add properties prefixed with `akismet` to the FormIt or Register snippet call. + +> Akismet works better the more information you provide. So look through the list of properties below and, if your form has a matching field, provide its name so it can be provided to Akismet. +> +> The snippet already automatically provides the IP, user agent, referrer, URL, etc. + +[TOC] + +## All Properties + +- `&akismetAuthor` - The author's name. +- `&akismetAuthorEmail` - The author's email. +- `&akismetAuthorUrl` - The author's URL if they provided one. +- `&akismetContent` - The message content. +- `&akismetType` - The type of form submitted. Available types include *comment*, *forum-post*, *reply*, *blog-post*, *contact-form*, *signup*, *message*, and more. Read more [here](https://blog.akismet.com/2012/06/19/pro-tip-tell-us-your-comment_type/). +- `&akismetUserRole` - The type of user e.g. *visitor*, or *member*. If set to *Administrator*, the form will never be blocked. +- `&akismetTest` - Set this to `1` while developing so the AI knows it is just a test submission. +- `&akismetHoneypotField` - If you use a hidden honeypot field in your form, set the name of it here. +- `&akismetRecheckReason` - If you have a form where the same submission needs to be checked more than once, include the reason for it here. +- `&akismetError` - The error message to set when the form failed the spam check. By default, this will use the `akismet.message_blocked` lexicon, which you may edit via System > Lexicon Management > akismet (select in the namespace dropdown), or you can provide the snippet property with a different message entirely. + +For example, if you have a contact form that has input fields like this: + +```html + + +``` + +Then you need to set at least the following properties: + +```html +[[!FormIt / Register? + &hooks=`Akismet,email,redirect` + ... + &akismetType=`contact-form` + &akismetAuthor=`sender` + &akismetAuthorEmail=`sender_email` + ... +]] +``` + +## Use with FormIt + +Add the snippet to the hooks: + + [[!FormIt? + ... + &hooks=`Akismet,email,redirect` + ... + ]] + +If you use other anti-spam or validation measures (like Recaptcha or CSRFHelper), you can decide in which order to place them. As Akismet may see repeat submits as spammy, you'll usually want to put other checks first. + +Also add as many of the snippet properties that matches your form names, for example a form with a `name`, `email` and `text` field, a hidden `nospam` honeypot field: + + &akismetType=`contact-form` + &akismetAuthor=`name` + &akismetAuthorEmail=`email` + &akismetContent=`text` + &akismetHoneypotField=`nospam` + +[See a full FormIt example](Examples/FormIt) + +## Use with Register + +On your register resource, add the Akismet snippet to the `&preHooks` on the Register snippet call: + + [[!Register? + ... + &preHooks=`Akismet` + ... + ]] + +Also add as many of the snippet properties that matches your form names, for example a form with a `username`, `email` and `fullname` field, a hidden `nospam` honeypot field, and while testing: + + &akismetType=`signup` + &akismetAuthor=`username` + &akismetAuthorEmail=`email` + &akismetContent=`fullname` + &akismetHoneypotField=`nospam` + +If you have split name fields, you can provide them as a comma separated list: + + &akismetContent=`firstname,lastname` + +[See a full Register example](Examples/Register) + +## Use with Quip (v1.1+) + +On your QuipReply snippet call, add the Akismet snippet to the `&preHooks`: + + [[!QuipReply? + ... + &preHooks=`Akismet` + ... + ]] + +Also add as many of the snippet properties that matches your form names, for example a form with a `username`, `email` and `fullname` field, a hidden `nospam` honeypot field, and while testing: + + &akismetType=`reply` + &akismetAuthor=`name` + &akismetAuthorEmail=`email` + &akismetAuthorUrl=`website` + &akismetContent=`comment` + &akismetHoneypotField=`nospam` + +[See a full Quip example](Examples/Quip) + + diff --git a/en/50_Open_Source/Akismet/Examples/FormIt.md b/en/50_Open_Source/Akismet/Examples/FormIt.md new file mode 100644 index 00000000..157eb75f --- /dev/null +++ b/en/50_Open_Source/Akismet/Examples/FormIt.md @@ -0,0 +1,85 @@ +--- +title: FormIt +description: Protecting FormIt forms against spam with Akismet +--- + +Here's a full contact form powered by FormIt, [based on the example from the MODX Documentation](https://docs.modx.com/current/en/extras/formit/formit.tutorials-and-examples/examples.simple-contact-page), adapted to include the [Akismet hook](../Akismet_Snippet) to protect against spam instead of Recaptcha. + +After installing FormIt, you can place this full form on a resource or in a chunk/template. + +> To learn more about FormIt, [see the official docs](https://docs.modx.com/current/en/extras/formit). + +```html +[[!FormIt? + &hooks=`Akismet,email,redirect` + &emailTpl=`MyEmailChunk` + &emailTo=`user@example.com` + &emailUseFieldForSubject=`1` + + &akismetTest=`1` + &akismetType=`contact-form` + &akismetAuthor=`name` + &akismetAuthorEmail=`email` + &akismetContent=`text` + &akismetHoneypotField=`nospam` + + &redirectTo=`6` + &validate=`nospam:blank, + name:required, + email:email:required, + subject:required, + text:required:stripTags` +]] + + +[[!+fi.validation_error_message:notempty=`

    [[!+fi.validation_error_message]]

    `]] +[[!+fi.error.akismet:notempty=`

    [[!+fi.error.akismet]]

    `]] + +
    + + + + + + + + + + + + + + +
    + +
    + +
    +
    +``` + +When you're done testing, make sure to remove the ```&akismetTest=`1` ``` property from the snippet. + +Also create the chunk for the email content named **MyEmailChuk**: + +```html +This is the Formit Email Chunk. + +
    [[+name]] ([[+email]]) Wrote:
    + +[[+text]] +``` + + diff --git a/en/50_Open_Source/Akismet/Examples/Quip.md b/en/50_Open_Source/Akismet/Examples/Quip.md new file mode 100644 index 00000000..a297e65c --- /dev/null +++ b/en/50_Open_Source/Akismet/Examples/Quip.md @@ -0,0 +1,25 @@ +--- +title: Quip +description: Protecting Quip threads from spam with Akismet +--- + +TBA + +## Basic usage + +On your QuipReply snippet call, add the Akismet snippet to the `&preHooks`: + + [[!QuipReply? + ... + &preHooks=`Akismet` + ... + ]] + +Also add as many of the snippet properties that matches your form names, for example a form with a `username`, `email` and `fullname` field, a hidden `nospam` honeypot field, and while testing: + + &akismetType=`reply` + &akismetAuthor=`name` + &akismetAuthorEmail=`email` + &akismetAuthorUrl=`website` + &akismetContent=`comment` + &akismetHoneypotField=`nospam` diff --git a/en/50_Open_Source/Akismet/Examples/Register.md b/en/50_Open_Source/Akismet/Examples/Register.md new file mode 100644 index 00000000..562c5eaf --- /dev/null +++ b/en/50_Open_Source/Akismet/Examples/Register.md @@ -0,0 +1,125 @@ +--- +title: Register +description: Protecting user registration forms against spam with Akismet +--- + +Register is part of the [Login package](https://modx.com/extras/package/login) and used for allowing users to create new accounts on your site. Akismet can protect against spam signups. + +The example below is based on the [example from the MODX documentation](https://docs.modx.com/current/en/extras/login/login.register/example-form-1), adapted to include the [Akismet hook](../Akismet_Snippet). + +[TOC] + +## Register resource + +Replace activationResourceId with the ID of the activation resource, and submittedResourceId with the ID of the resource that instructs (see below). + +```html +

    Register

    + +[[!Register? + &submitVar=`registerbtn` + + &preHooks=`Akismet` + + &akismetTest=`1` + &akismetType=`signup` + &akismetAuthor=`username` + &akismetAuthorEmail=`email` + &akismetContent=`fullname` + &akismetHoneypotField=`nospam` + + &activationResourceId=`123` + &activationEmailTpl=`myActivationEmailTpl` + &activationEmailSubject=`Thanks for Registering!` + &submittedResourceId=`45` + &usergroups=`Marketing,Research` + &validate=`nospam:blank, + username:required:minLength=^6^, + password:required:minLength=^6^, + password_confirm:password_confirm=^password^, + fullname:required, + email:required:email` + &placeholderPrefix=`reg.` +]] + +
    +
    [[!+reg.error.message]]
    + +
    + + + + + + + + + + + + + + + + + +
    + +
    + +
    +
    +
    +``` + +If you do not use the `[[!+reg.error.message]]` placeholder (which will contain all errors), you can render the Akismet error specifically like this: + + [[!+register.error.akismet:notempty=`

    [[!+register.error.akismet]]

    `]] + +In the **myActivationEmailTpl** chunk: + +```html +

    [[+username]],

    + +

    Thanks for registering! To activate your new account, please click on the following link:

    + +

    [[+confirmUrl]]

    + +

    After activating, you may login with your password and username:

    + +

    +Username: [[+username]]
    +Password: [[+password]]

    + +

    If you did not request this message, please ignore it.

    + +

    Thanks,
    +Site Administrator

    +``` + +## Submitted resource + +The submitted resource is used to tell people their account was created, but they need to check their email to click the activation link. It requires no special snippet, but you do need to refer to it in the Register snippet above (`&submittedResourceId`). + +## Activation Resource + +The activation resource needs to have the [ConfirmRegister snippet](https://docs.modx.com/current/en/extras/login/login.confirmregister) on it. + +```html +[[!ConfirmRegister]] +``` + +It's suggested to at least provide a &errorPage property if there's an issue confirming the new account, and/or the &redirectTo property. + +Set the ID of your activation resource to `&activationResourceId` on the Register snippet. + diff --git a/en/50_Open_Source/Akismet/Examples/Standalone.md b/en/50_Open_Source/Akismet/Examples/Standalone.md new file mode 100644 index 00000000..2fa36df7 --- /dev/null +++ b/en/50_Open_Source/Akismet/Examples/Standalone.md @@ -0,0 +1,94 @@ +--- +title: Standalone usage +--- + +If you use custom form-handling snippets in MODX that you want to protect against spam with Akismet, you can re-use our work (v1.1+). + +[TOC] + +## Grab the Akismet class + +Akismet is not automatically loaded as a service, we recommend the following code to check if it is installed/available: + +```php +getOption('akismet.core_path', null, MODX_CORE_PATH . 'components/akismet/'); +$path .= 'vendor/autoload.php'; +if (!file_exists($path)) { + // Handle the case where akismet is not available + return "Unable to check for spam"; +} +require_once $path; +``` + +## Check for spam + +Next, create an instance of the `modmore\Akismet\Akismet` class, and call the checkSpam method. Because both the instantiation and checkSpam can cause an exception, wrap the whole thing in a `try {} catch () {}` block. + +```php +try { + $akismet = new Akismet($modx); + $values = ...; // see below + $config = ...; // see below + $isSpam = $akismet->checkSpam($values, $config); + if ($isSpam) { + // Handle spammy form submissions + } +} +catch (InvalidAPIKeyException $e) { + $modx->log(modX::LOG_LEVEL_ERROR, 'Akismet API key not found. Please add it in the MODX system settings. Form is submitting without a spam check...'); +} +catch (GuzzleException $e) { + $modx->log(modX::LOG_LEVEL_ERROR, $e->getMessage() . ': ' . $e->getTraceAsString()); +} +catch (xPDOException $e) { + $modx->log(modX::LOG_LEVEL_ERROR, $e->getMessage() . ': ' . $e->getTraceAsString()); +} +``` + +## Passing $values and $config options + +There are two ways to provide configuration to the class. + +1. Provide an array of submitted values in `$values`, and an array of `$config` that matches the [snippet properties](../Akismet_Snippet). +2. Provide only an array of values, already using the Akismet keys. + +An example of option 1: + +```php +// could just be $values = $_POST, but in this case we want to show the structure of the array +$values = [ + 'name' => $_POST['name'], + 'email' => $_POST['email'], + 'message' => $_POST['message'], +]; + +// could just be $config = $scriptProperties, but in this case we want to show the structure of the array +$config = [ + 'akismetType' => 'signup' + 'akismetAuthor' => 'name', + 'akismetAuthorEmail' => 'email', + 'akismetContent' => 'message' +]; + +$isSpam = $akismet->checkSpam($values, $config); +// or: +$isSpam = $akismet->checkSpam($_POST, $scriptProperties); +``` + +An example of option 2: + +```php +// Note the key names must now match the Akismet api @ https://akismet.com/development/api/#comment-check +$values = [ + 'comment_type' => 'signup', + 'comment_author' => $_POST['name'], + 'comment_author_email' => $_POST['email'], + 'comment_content' => $_POST['message'], +]; + +$isSpam = $akismet->checkSpam($values); +``` + +These are functionally identical. Option 1 is easier to implement in a snippet (just pass `$_POST` and `$scriptProperties` and configure it like you would FormIt or Register), while option 2 gives you a bit more control. + diff --git a/en/50_Open_Source/Akismet/index.md b/en/50_Open_Source/Akismet/index.md new file mode 100644 index 00000000..33b6882d --- /dev/null +++ b/en/50_Open_Source/Akismet/index.md @@ -0,0 +1,47 @@ +--- +title: Akismet +--- + + +[Akismet](https://akismet.com/) is an advanced spam protection service that uses AI to analyse form submissions. It learns from spam patterns around the web in real-time, and is extremely effective at blocking spam without hindering the user experience with CAPTCHAs. + +Originally developed for Wordpress, this open source package integrates Akismet with the MODX extras +[FormIt](https://docs.modx.com/current/en/extras/formit/index) and [Login](https://docs.modx.com/current/en/extras/login/index) (specifically the [Register](https://docs.modx.com/current/en/extras/login/login.register) snippet). + +Akismet is free for personal sites or blogs, and requires a paid subscription for use on commercial websites. [Learn more about Akismet's subscription model](https://akismet.com/plans/). + +[Donations to support our open source work are much appreciated](https://modmore.com/extras/akismet/donate/). + +[TOC] + +## Getting Started + +Install Akismet via the [modmore package provider](https://modmore.com/about/package-provider/). + +[Sign up for an Akismet account](https://akismet.com/plans/), then copy and paste the provided *API Key* into the new `akismet.api_key` system setting. + +Next, [implement the Akismet snippet](Akismet_Snippet) as either a hook (FormIt) or preHook (Register, QuipReply) into your form. If you have a custom form-handling snippet, [see the standalone instructions](Examples/Standalone). + +## Personal information + +Because personal information is sent to a third party, using the Akismet package touches on GDPR and similar regulation. + +As spam protection is a "legitimate interest" its usage does not require specific consent. That said, it's worth adding a notice in your Privacy Policy, and/or adding a line like this to your forms: + +> This site uses Akismet to reduce spam. Learn how your comment data is processed. + +[Learn more about Akismet and the GDPR.](https://akismet.com/gdpr/) + +## Automatic cleanup (v1.1+) + +Spam checks are automatically removed after 30 days. This time period can be adjusted with the `akismet.cleanup_days_old` system setting; giving it a value of 0 disables the cleanup. + +The cleanup does not require a cron job, but runs automatically when form submissions are checked for spam. + +## + +## Learn More + +- [Akismet snippet reference and usage instructions](Akismet_Snippet) +- [FormIt example](Examples/FormIt) +- [Register example](Examples/Register) diff --git a/en/50_Open_Source/BigBrother/Custom_oAuth_Credentials.md b/en/50_Open_Source/BigBrother/Custom_oAuth_Credentials.md new file mode 100644 index 00000000..6a295c12 --- /dev/null +++ b/en/50_Open_Source/BigBrother/Custom_oAuth_Credentials.md @@ -0,0 +1,25 @@ + +> **As of February 28th 2022, new oAuth credentials are no longer allowed to use the "out-of-band" oAuth flow** which is used by Big Brother v1 and v2. [Google has decided to deprecate it](https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html) and to remove it entirely on October 3rd, 2022. +> +> New credentials will **not** be able to authorize Google accounts through newly created credentials as outlined below. Only credentials created prior to February 28th, 2022 will work until October 3rd, 2022. +> +> Big Brother 3.0 has been released on August 25th with a new authorization process which will work after that date. However, it is no longer possible to use custom credentials. + +## Big Brother v3 + +Due to the use of an authorization proxy with the new authentication flow, it's not possible to use custom oAuth credentials in v3. If you'd like to sponsor the development of support for custom proxies, get in touch. + +## Big Brother v2 + +If you prefer to use your own credentials to authenticate with Google, here's how to do that. + +1. [Login to the Google Cloud API Console](https://console.developers.google.com/) +2. Create a project in the projects dropdown +3. Add the **Google Analytics API**, **Google Analytics Data API**, and **Google Analytics Admin API** to the project +4. Under oAuth permission screen, configure the type of app to either be internal (if only users within your Google organisation will need to authorise) or External (which will require app review from Google beyond 100 users). Also add a name and add the Google Analytics realm to the permissions. +5. In Credentials, click the button at the top and choose to create a new oAuth Client-ID. +6. For the Type, choose Desktop App. +7. Copy the Client ID to the "bigbrother.native_app_client_id" system setting in MODX +8. Copy the Client Secret to the "bigbrother.native_app_client_secret" system setting in MODX + +Once you've done this, you can reuse your credentials among different projects. diff --git a/en/50_Open_Source/BigBrother/Privacy.md b/en/50_Open_Source/BigBrother/Privacy.md new file mode 100644 index 00000000..e2d48ed0 --- /dev/null +++ b/en/50_Open_Source/BigBrother/Privacy.md @@ -0,0 +1,23 @@ +If you install Big Brother from the modmore package provider, technical information from your site may be collected in accordance with the modmore [terms of service](https://modmore.com/tos/) and [privacy policy](https://modmore.com/privacy/). + +In addition to that, it's worth noting how the authorization process with your Google account works and affects your privacy. + +## Big Brother v3 + +When authorizing your MODX site with Google, you use an authorization proxy hosted by modmore. This authorization proxy takes care of the redirect steps in the OAuth authentication flow and, once approved, receives access to the `authorization_code`. + +The `authorization_code` is a short-lived token (valid for only a few minutes) which can be exchanged for a `refresh_token` exactly once. The `refresh_token` is able of accessing your accounts' Google Analytics data until revoked. + +If through the authorization proxy you approve sharing access with your site, the `authorization_code` is submitted to your website, which will then exchange it for a `refresh_token` locally to your site. [This can be confirmed in the open source Big Brother code](https://github.com/modmore/BigBrother/blob/2.x/core/components/bigbrother/controllers/authorize.class.php#L73). Once converted to the `refresh_token` on your site, the resulting tokens to access your sites' analytics data are only ever stored in your own site, and we literally cannot access anything, meaning your privacy is ensured. + +In theory, the `authorization_code` may appear in server-level logging on the modmore server. Only in the short window before you accept sharing the `authorization_code` with your site and its expiration could modmore in theory claim a `refresh_token` to access your sites' data. We have no interest in doing so, and if this were to happen, you would receive an error when returning to your site. + +If you wish to revoke access to your account, [visit your Google Security Profile](https://myaccount.google.com/permissions), find Big Brother for MODX in the list of _Third-party Apps with account access_, and click on _Remove Access_. + +## Big Brother v1 and v2 + +When authorizing your MODX site with Google, the oauth screen says you're giving access to Mark Hamstra Web Development. + +While technically that's true, the resulting tokens and keys that allow access to your sites' analytics data are only ever stored in your own site. Therefore, we literally cannot access your sites analytics data. + +If you wish to revoke access to your account, [visit your Google Security Profile](https://myaccount.google.com/permissions), find Big Brother for MODX in the list of _Third-party Apps with account access_, and click on _Remove Access_. diff --git a/en/50_Open_Source/BigBrother/index.md b/en/50_Open_Source/BigBrother/index.md new file mode 100644 index 00000000..dd26d0da --- /dev/null +++ b/en/50_Open_Source/BigBrother/index.md @@ -0,0 +1,11 @@ +[Big Brother](https://modx.com/extras/package/bigbrother) is an [open source extra](https://github.com/modmore/BigBrother) that allows you to see your google analytics data on the MODX dashboard. + +[Privacy policy](Privacy) or [Use your own credentials](Custom_oAuth_Credentials) + +Different version of Big Brother are available. + +- Big Brother **v3** supports Google Analytics v4 on both MODX 3.x and 3.x. It is actively supported and maintained. +- Big Brother **v2** supports Google Analytics v4 on both MODX 2.x and 3.x. v2 is **deprecated**, only receiving security updates, and will be **end-of-life on October 3rd, 2022**. +- Big Brother **v1** supports Universal Analytics on MODX 2.x only. v1 is **deprecated**, only receiving security updates, and will be **end-of-life on July 1st, 2023**. (Note that [Universal Analytics will be end-of-life](https://support.google.com/analytics/answer/11583528?hl=en) on that same date.) + +[Learn more about the v1 and v2 deprecation in the v3 announcement](https://modmore.com/blog/2022/big-brother-3.0-now-available/). diff --git a/en/50_Open_Source/CSRFHelper/FormIt.md b/en/50_Open_Source/CSRFHelper/FormIt.md new file mode 100644 index 00000000..32e9d886 --- /dev/null +++ b/en/50_Open_Source/CSRFHelper/FormIt.md @@ -0,0 +1,82 @@ +CSRFHelper can protect your FormIt forms against CSRF attacks. + +[TOC] + +## Adding the token to the form + +In your form, add the following hidden field: + + + +**» Note:** the `&key` property needs to match the `&csrfKey` property we add to the FormIt snippet call in a minute. + +For sensitive forms, you can also add a `&singleUse` property with value 1 that ensures each request gets a unique CSRF token. If you leave this out, the token for the form is the same for up to 24 hours. + +To show the error when the CSRF token does not match, or if it can't be securely generated on your server, add the following in an appropriate place in your form: + + [[!+fi.error.csrf_token:notempty=`
    [[!+fi.error.csrf_token]]
    `]] + +## Validating the token with a hook + +Now that we're submitting the token, we should also validate it. We do this with the `csrfhelper_formit` hook. + +In the FormIt snippet call, add the `csrfhelper_formit` to your `&hooks` property. + +Also add the `&csrfKey` property with the key for the CSRF token; this should be unique for each unique form and match the `&key` in the `csrfhelper` snippet call. In the example above, this was set to `simple-form`. + +## Full example + +Below is a full example based on the [simple contact form example for FormIt](https://docs.modx.com/extras/revo/formit/formit.tutorials-and-examples/formit.examples.simple-contact-page). + +```` html +[[!FormIt? + &hooks=`spam,csrfhelper_formit,email,redirect` + &redirectTo=`71` + &validate=`nospam:blank, + name:required, + email:email:required, + subject:required, + text:required:stripTags` + &csrfKey=`simple-form` +]] + + +

    Contact Form

    + +[[!+fi.validation_error_message:notempty=`

    [[!+fi.validation_error_message]]

    `]] + +
    + [[!+fi.error.csrf_token:notempty=`
    [[!+fi.error.csrf_token]]
    `]] + + + + + + + + + + + + + + + +
    + +
    +
    +```` + diff --git a/en/50_Open_Source/CSRFHelper/Login/01_Login.md b/en/50_Open_Source/CSRFHelper/Login/01_Login.md new file mode 100644 index 00000000..dddedbb3 --- /dev/null +++ b/en/50_Open_Source/CSRFHelper/Login/01_Login.md @@ -0,0 +1,97 @@ +CSRFHelper can protect your login forms from the [Login package](https://modx.com/extras/package/login) against CSRF attacks. + +[TOC] + +## Adding the token to the Login form + +First, we need to define a custom chunk to use as the login form if you haven't already done that: + + [[!Login? + &tplType=`modChunk` + &loginTpl=`myLoginTpl` + ]] + +Edit the `myLoginTpl` chunk. Based on the default `lgnLoginTpl` chunk, that might look like this: + +````html +
    +
    [[+errors]]
    +
    +
    +
    + [[+actionMsg]] + + + + + + [[+login.recaptcha_html]] + + + +
    +
    +
    +
    +```` + +Inside the `
    `, add a hidden field like so: + + + +Note that we're adding `&singleUse` here. Logging in a sensitive action, so we only want each token to be used once. We're also setting the `&key` to `login`, which we'll need to also set in the Login snippet in a minute. + +While for [Formit](../FormIt) we need to separately add an error placeholder to show when the security token isn't valid, that's not needed for Login. The `[[+errors]]` placeholder will show the error automatically. + +The full example `myLoginTpl` chunk, including the `csrf_token` hidden field, now looks like this: + +````html +
    +
    [[+errors]]
    +
    + + + +
    + [[+actionMsg]] + + + + + + [[+login.recaptcha_html]] + + + +
    + +
    +
    +```` + +## Validating the token with a hook + +Now that we're submitting the token, we should also validate it. We do this with the `csrfhelper_login` pre-hook. + +In the Login snippet call, add the `csrfhelper_login` to your `&preHooks` property. + +Also add the `&csrfKey` property with the key for the CSRF token; this should be unique for each unique form and match the `&key` in the `csrfhelper` snippet call. In the example above, this was set to `login`. + +All things combined, our Login snippet now looks like this: + +````html +[[!Login? + &tplType=`modChunk` + &loginTpl=`myLoginTpl` + &preHooks=`csrfhelper_login` + &csrfKey=`login` +]] +```` diff --git a/en/50_Open_Source/CSRFHelper/Login/02_Register.md b/en/50_Open_Source/CSRFHelper/Login/02_Register.md new file mode 100644 index 00000000..73680cbe --- /dev/null +++ b/en/50_Open_Source/CSRFHelper/Login/02_Register.md @@ -0,0 +1,75 @@ +CSRFHelper can protect your registration forms from the [Login package](https://modx.com/extras/package/login) against CSRF attacks. + +[TOC] + +## Adding the token to the form and hook + +In your registration form, add a hidden input with name csrf_token that calls the `csrfhelper` snippet: + + + +We're adding `&singleUse` here so each request to the registration page gets a new token. If you leave that off, the token will be valid for 24 hours. + +## Validating the token + +On the Register snippet call, add the `csrfhelper_login` to the `&preHooks`, and set `&csrfKey` to the same key in the `csrfhelper` snippet, so `register` in the example above. + +Taking the [example form from the official documentation](https://docs.modx.com/extras/revo/login/login.register/register.example-form-1), and adding the necessary tweaks, you'll end up with a form like this: + +````html +[[!Register? + &submitVar=`registerbtn` + &submittedResourceId=`73` + &preHooks=`csrfhelper_login` + &csrfKey=`register` + &usergroups=`Marketing,Research` + &validate=`nospam:blank, + username:required:minLength=^6^, + password:required:minLength=^6^, + password_confirm:password_confirm=^password^, + fullname:required, + email:required:email` + &placeholderPrefix=`reg.` +]] + +
    +
    [[!+reg.error.message]]
    + +
    + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    +
    +
    +```` diff --git a/en/50_Open_Source/CSRFHelper/Login/03_UpdateProfile.md b/en/50_Open_Source/CSRFHelper/Login/03_UpdateProfile.md new file mode 100644 index 00000000..ea032507 --- /dev/null +++ b/en/50_Open_Source/CSRFHelper/Login/03_UpdateProfile.md @@ -0,0 +1,109 @@ +CSRFHelper can protect your update profile forms from the [Login package](https://modx.com/extras/package/login) against CSRF attacks. + +[TOC] + +## Adding the token to the form + +In your registration form, add a hidden input with name csrf_token that calls the `csrfhelper` snippet: + + + +We're adding `&singleUse` here so each request to the form page gets a new token. If you leave that off, the token will instead be valid for 24 hours. + +## Validating the token + +On the [UpdateProfile](https://docs.modx.com/extras/revo/login/login.updateprofile) snippet call, add the `csrfhelper_login` to the `&preHooks`, and set `&csrfKey` to the same key in the `csrfhelper` snippet, so `updateprofile` from the example above. + +For example: + +````html +[[!UpdateProfile? + &validate=`fullname:required,email:required:email` + &preHooks=`csrfhelper_login` + &csrfKey=`updateprofile` +]] +```` + +## Full example + +Based on the [example from the documentation](https://docs.modx.com/extras/revo/login/login.updateprofile), your form might end up looking like this: + +````html +[[!UpdateProfile? + &validate=`fullname:required,email:required:email` + &preHooks=`csrfhelper_login` + &csrfKey=`updateprofile` +]] + + +
    +
    [[+error.message]]
    + [[+login.update_success:is=`1`:then=`[[%login.profile_updated? &namespace=`login` &topic=`updateprofile`]]`]] + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +
    +
    +
    +```` diff --git a/en/50_Open_Source/CSRFHelper/Login/04_ChangePassword.md b/en/50_Open_Source/CSRFHelper/Login/04_ChangePassword.md new file mode 100644 index 00000000..f44b9518 --- /dev/null +++ b/en/50_Open_Source/CSRFHelper/Login/04_ChangePassword.md @@ -0,0 +1,65 @@ +CSRFHelper can protect your change password forms from the [Login package](https://modx.com/extras/package/login) against CSRF attacks. + +[TOC] + +## Adding the token to the form + +In your change password form, add a hidden input with name csrf_token that calls the `csrfhelper` snippet: + + + +We're adding `&singleUse` here so each request to the form page gets a new token. If you leave that off, the token will instead be valid for 24 hours. + +## Validating the token + +On the [ChangePassword](https://docs.modx.com/extras/revo/login/login.changepassword) snippet call, add the `csrfhelper_login` to the `&preHooks`, and set `&csrfKey` to the same key in the `csrfhelper` snippet, so `changepassword` from the example above. + +For example: + +````html +[[!ChangePassword? + &preHooks=`csrfhelper_login` + &csrfKey=`changepassword` +]] +```` + +## Full example + +Based on the [example from the documentation](https://docs.modx.com/extras/revo/login/login.changepassword), your form might end up looking like this: + +````html +[[!ChangePassword? + &submitVar=`change-password` + &placeholderPrefix=`cp.` + &validateOldPassword=`1` + &validate=`nospam:blank` + &preHooks=`csrfhelper_login` + &csrfKey=`changepassword` +]] +
    [[!+cp.error_message]]
    +
    + + +
    + + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    +```` diff --git a/en/50_Open_Source/CSRFHelper/index.md b/en/50_Open_Source/CSRFHelper/index.md new file mode 100644 index 00000000..047ae6ab --- /dev/null +++ b/en/50_Open_Source/CSRFHelper/index.md @@ -0,0 +1,105 @@ +CSRF Helper is a tool for MODX to secure forms against cross-site request forgery (CSRF) vulnerabilities, brought to you by [modmore](https://modmore.com/). + +[TOC] + +## What's a CSRF vulnerability? + +The [Open Web Application Security Project (OWASP) explains CSRF](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)) as follows: + +> Cross-Site Request Forgery (CSRF) is an attack that forces an end user to +execute unwanted actions on a web application in which they're currently authenticated. +CSRF attacks specifically target state-changing requests, not theft of data, since the +attacker has no way to see the response to the forged request. + +> With a little help of social engineering (such as sending a link via email or chat), +an attacker may trick the users of a web application into executing actions of the +attacker's choosing. + +> If the victim is a normal user, a successful CSRF attack can force the user to perform +state changing requests like transferring funds, changing their email address, and so forth. +If the victim is an administrative account, CSRF can compromise the entire web application. + +Forms that are vulnerable to CSRF can be executed by an attacker as another (authenticated) user. This requires that +the user can be tricked into executing the action from their browser, for example by visiting a compromised site +or a link that exploits a cross-site-scripting (XSS) vulnerability. + +Most CSRF attacks are thus targeted. They are also specific to a site, as the attacker will need to craft a specific +request for specific sites and forms. This makes CSRF a lower risk vulnerability to the average site compared to, say, +a SQL injection or persisted XSS that impacts all visitors of a site. + +You should however care about CSRF vulnerabilities if authenticated users can execute actions that can impact your +site, their usage of the site, or lead to other vulnerabilities. + +For example, a simple contact form that only sends information via email that the user submits is not as vulnerable +as a form that lets the user change the email address or other personal information associated with their account. +The latter could lead to an account being taken over by an attacker, while the first is just spam. + +The benefit of implementing CSRF Helper on less vulnerable forms (like contact forms) comes from its potential to help +protect against spam. An unprotected form can easily be hammered by an attacker/spammer, while a protected form requires +the attacker to at the very least request the page containing the form over and over again and interact with it. + +## How does CSRF Helper protect against CSRF? + +With CSRF Helper you can add CSRF protection to any form built with FormIt, as well as forms for the Login package. +It's also possible, though currently not documented, to use the PHP classes at the core of CSRF Helper to verify tokens +in custom form handlers. + +The CSRF protection works by generating what's known as a CSRF token, a random hash that is stored in a users' session, +and which needs to be present and correct in a form submission. As an attacker cannot know this token in advance, they +are unable of executing a valid form submission. + +Other types of vulnerabilities (in particular XSS or clickjacking) may bypass this CSRF protection, but CSRF tokens do +add a very valuable layer of protection. + +## Download & Installation + +CSRFHelper is free to use, and licensed under the MIT License. [Source code and issue tracker are on GitHub](https://github.com/modmore/csrfhelper). + +Installable packages are available from both [modmore](https://modmore.com/extras/csrfhelper/) and [MODX](https://modx.com/extras/package/csrfhelper), through your site's package manager. After installation, look at the specific documentation for the type of form you're looking to protect for examples and instructions. + +## Usage + +After installing the extra, you get access to some new snippets: + +- `csrfhelper` returns a CSRF token that you need to insert into the form (typically as a hidden input with name `csrf_token`) that is submitted along with the request. +- `csrfhelper_formit` is meant to be used as a FormIt hook to validate the `csrf_token` variable. +- `csrfhelper_login` is meant to be used as a hook on snippets provided by Login (Login, Register, UpdateProfile) to validate the `csrf_token` variable in those requests. + +The **csrfhelper** snippet is used to generate the token. The other snippets are used for validating the token with specific tools. + +- [Protecting FormIt forms against CSRF](FormIt) +- Login: + - [Protecting login forms against CSRF](Login/Login) + - [Protecting registration forms against CSRF](Login/Register) + - [Protecting update profile forms against CSRF](Login/UpdateProfile) + - [Protecting change password forms against CSRF](Login/ChangePassword) + +### csrfhelper snippet + +The csrfhelper snippet generates the token for most uses. + +It accepts the following properties: + +- **`key`**: required, the identifier for the token. This should be unique for most forms. +- **`singleUse`**: optional, when set to 1 the token will only be valid for one request. Subsequent requests will generate a new token. Recommended for sensitive forms or forms that have a destructive outcome. + +### csrfhelper_formit snippet + +Used as hook for FormIt. + +- Accepts a `csrfKey` property that should match the `key` property on `csrfhelper`. +- Expects the token to be provided in a field named `csrf_token` +- Validation errors are set to the `[[!+fi.error.csrf_token]]` placeholder + +[Learn how to protect your FormIt forms](FormIt) + +### csrfhelper_login snippet + +Used as hook for snippets that come with the Login package, including Login, Register, UpdateProfile and ChangePassword. + +- Accepts a `csrfKey` property that should match the `key` property on `csrfhelper`. +- Expects the token to be provided in a field named `csrf_token` +- Validation errors are returned to the respective snippet with no specific placeholder needed. See the documentation for each snippet for the placeholder that contains the error; these placeholders are already present in the default templates. + +[Learn how to protect your Login forms](Login/Login) + diff --git a/en/50_Open_Source/ClientConfig/03_Field_Types.md b/en/50_Open_Source/ClientConfig/03_Field_Types.md index 93102eba..cefcaf2d 100644 --- a/en/50_Open_Source/ClientConfig/03_Field_Types.md +++ b/en/50_Open_Source/ClientConfig/03_Field_Types.md @@ -7,7 +7,7 @@ You can choose a number of field types for your configurations. It's not current The textfield is a simple single-line textfield. -![](https://www.modmore.com/assets/uploads/2014/02/6.png) +![](https://modmore.com/assets/uploads/2014/02/6.png) ExtJS Type: `textfield` @@ -15,7 +15,7 @@ ExtJS Type: `textfield` The textarea is a simple multi-line textfield. -![](https://www.modmore.com/assets/uploads/2014/02/5.png) +![](https://modmore.com/assets/uploads/2014/02/5.png) ExtJS Type: `textarea` @@ -25,7 +25,7 @@ The Rich Text field is a simple multi-line textfield that will get enhanced to a The following MODX RTE extras are supported: -- [Redactor from modmore](https://www.modmore.com/redactor/) +- [Redactor from modmore](https://modmore.com/redactor/) - TinyMCE - TinyMCE RTE - CKEditor is partially supported with known issues. @@ -36,7 +36,7 @@ ExtJS Type: `textarea`, enhanced with `MODx.loadRTE` Provides an input that opens the MODX Browser to select an image. Can be configured to a specific media source through the _Source_ option on the field. -![](https://www.modmore.com/assets/uploads/2014/02/4.png) +![](https://modmore.com/assets/uploads/2014/02/4.png) ExtJS Type: `modx-panel-tv-image` @@ -50,7 +50,7 @@ ExtJS Type: `modx-panel-tv-file` A simple field that only accepts numbers. -![](https://www.modmore.com/assets/uploads/2014/02/7.png) +![](https://modmore.com/assets/uploads/2014/02/7.png) ExtJS Type: `numberfield` @@ -58,7 +58,7 @@ ExtJS Type: `numberfield` Allows the user to pick a color with a visual color picker. -![](https://www.modmore.com/assets/uploads/2014/02/1.png) +![](https://modmore.com/assets/uploads/2014/02/1.png) ExtJS Type: `colorpickerfield` @@ -66,7 +66,7 @@ ExtJS Type: `colorpickerfield` Allows a user to toggle something on or off. -![](https://www.modmore.com/assets/uploads/2014/02/2.png) +![](https://modmore.com/assets/uploads/2014/02/2.png) ExtJS Type: `xcheckbox` @@ -82,7 +82,7 @@ ExtJS Type: `textfield` with `inputType` set to `password` Pick a date. -![](https://www.modmore.com/assets/uploads/2014/02/9.png) +![](https://modmore.com/assets/uploads/2014/02/9.png) ExtJS Type: `datefield` @@ -90,7 +90,7 @@ ExtJS Type: `datefield` Pick a time. -![](https://www.modmore.com/assets/uploads/2014/02/8.png) +![](https://modmore.com/assets/uploads/2014/02/8.png) ExtJS Type: `timefield` @@ -102,7 +102,7 @@ This follows the syntax of listbox template variables where options are separate `Display==Value||Other Display==OtherValue` -![](https://www.modmore.com/assets/uploads/2014/02/10.png) +![](https://modmore.com/assets/uploads/2014/02/10.png) If you enable _Process tags in options_ on the field, you can also use chunk or snippet tags to dynamically populate the dropdown. diff --git a/en/50_Open_Source/ClientConfig/index.md b/en/50_Open_Source/ClientConfig/index.md index 70a4f0e9..3ca4d5d5 100644 --- a/en/50_Open_Source/ClientConfig/index.md +++ b/en/50_Open_Source/ClientConfig/index.md @@ -10,5 +10,5 @@ Important links: - [Getting Started](Getting_started) - [Github](https://github.com/modmore/ClientConfig), for bug reports, feature requests, and access to the full MIT-licensed source code. -- [ClientConfig on modmore.com](https://www.modmore.com/extras/clientconfig/). +- [ClientConfig on modmore.com](https://modmore.com/extras/clientconfig/). - [ClientConfig on MODX.com](https://modx.com/extras/package/clientconfig). diff --git a/en/50_Open_Source/Dashbored/images/background-settings.jpg b/en/50_Open_Source/Dashbored/images/background-settings.jpg new file mode 100644 index 00000000..01a62cb5 Binary files /dev/null and b/en/50_Open_Source/Dashbored/images/background-settings.jpg differ diff --git a/en/50_Open_Source/Dashbored/images/dashbored-view.jpg b/en/50_Open_Source/Dashbored/images/dashbored-view.jpg new file mode 100644 index 00000000..300e05b5 Binary files /dev/null and b/en/50_Open_Source/Dashbored/images/dashbored-view.jpg differ diff --git a/en/50_Open_Source/Dashbored/index.md b/en/50_Open_Source/Dashbored/index.md new file mode 100644 index 00000000..01d27217 --- /dev/null +++ b/en/50_Open_Source/Dashbored/index.md @@ -0,0 +1,59 @@ +--- +title: Dashbored +--- + + +Dashbored is a collection of dashboard widgets for MODX 3.0+ + +Widgets included: + +* Weather +* Daily Quotes +* News Feed +* Dino Game +* SiteDash +* SiteDash | Extended Monitoring + +![An overview of the MODX dashbored utilising Dashbored widgets.](images/dashbored-view.jpg) + +_The image above shows the six different kinds of widgets available. Some are using custom backgrounds, and some are the default._ + +[TOC] + +## Getting Started + +Install Dashbored via the [modmore package provider](https://modmore.com/about/package-provider/). Then go to your MODX dashboard, and click on the **Add** button (in the top-right corner) to select the widgets you would like to use. + +## SiteDash Widgets + +There are two widgets that utilise your SiteDash account, enabling you to display both website audit and extended monitoring data. + +For these you will need to add your SiteDash Integration Key to the `dashbored.sitedash site_integration_key` system setting. You can generate a **SiteDash Integration Key** by logging into [SiteDash](https://sitedash.app/), select the site you would like to use, click on _Manage & Actions_, and you'll find it halfway down the page. + +After adding the site integration key to the system setting, return to your dashboard and click the refresh icon in the widget title bar to load the new data. + +## Settings + +Clicking on the cog icon in the widget title bar will open the settings window for that particular widget. What settings are available differ with widget but generally there will be a `Settings` tab, a `Background` tab and an `About` tab (except for the Dino Game widget which also has a `High Scores` tab). + +The settings tab will have fields to configure the data for that widget, for example the weather widget allows for changing the location, the temperature format, and distance measurements. + +The background tab lets you choose between using the default background, an image, and a video. Hover over the image box and a `Select image` button will appear. You can then click it to open the MODX file browser. There is also a slider control to darken the image or video background so that the text can still easily be seen over the top. + +![Change your widget background to an image or video of your choice.](images/background-settings.jpg) + +Configuration data for each widget is stored as user settings. So, each user can set up their widgets according to their own taste. + +The About tab contains information about the API, service, or GitHub repository that widget uses. + +## Refreshing the widget + +Data from the widgets is cached for a certain amount of time, so each time you return to the dashbored, you don't need to wait for responses from the various APIs. If you would like to refresh the widget before the cache has expired, click on the refresh icon in the widget's title bar. + +## Restricting access to widgets + +If there are certain widgets that you would like to restrict access to, this can be done via MODX main menu: +``` +Cog Icon -> Dashboards -> Widgets Tab -> Select the widget -> Permission dropdown +``` +From the list, select the permission a user needs to have to add that widget to the dashboard. \ No newline at end of file diff --git a/en/50_Open_Source/Gitify/01_Installation/01_Windows.md b/en/50_Open_Source/Gitify/01_Installation/01_Windows.md index 320f3a4f..41ef46bc 100644 --- a/en/50_Open_Source/Gitify/01_Installation/01_Windows.md +++ b/en/50_Open_Source/Gitify/01_Installation/01_Windows.md @@ -16,6 +16,12 @@ c:\xampp\php\php.exe \php\php.exe ```` +## MAMP Pro + +If you use MAMP Pro make sure to enable "[Make this version available on the command line](https://documentation.mamp.info/en/MAMP-PRO-Windows/Languages/PHP/)": + +> Check this option to add the current PHP version to the system path. You verify this by checking your System PATH in Advanced System Settings > Environment Variables > System Variables. + ### Additional Dependencies Here are the Windows dependencies in order to get the script to execute properly. They must be installed and their bin folders have to be added to the Windows PATH environment variable in the Advanced System Settings screen: @@ -29,4 +35,4 @@ Here are the Windows dependencies in order to get the script to execute properly * windows composer support (https://getcomposer.org) * Binary download - https://getcomposer.org/Composer-Setup.exe -Once those are completed, the rest of the instructions do work. \ No newline at end of file +Once those are completed, the rest of the instructions do work. diff --git a/en/50_Open_Source/Gitify/01_Installation/index.md b/en/50_Open_Source/Gitify/01_Installation/index.md index 17afd13e..d97acf88 100644 --- a/en/50_Open_Source/Gitify/01_Installation/index.md +++ b/en/50_Open_Source/Gitify/01_Installation/index.md @@ -1,14 +1,50 @@ +## v2 + +As of Gitify v2 and up, installation has been simplified and is handled entirely via composer. You can choose to install Gitifiy globally, or locally to a project. + +For a **global** installation, run: + +```` +composer global require modmore/gitify:^2 +```` + +After the installation completes, you'll use `gitify` as the main command. + +For a **local project installation**, run: + +```` +composer require modmore/gitify:^2 +```` + +After the installation completes, you'll use `vendor/bin/gitify` as the main command. + +Finally, for **development or advanced usage**, you may continue to use the manual installation steps: + +```` +git clone https://github.com/modmore/Gitify.git Gitify +cd Gitify +composer install --no-dev +chmod +x bin/gitify +```` + +In this case you'll use `bin/gitify` as the main command. + +_Note that the gitify executable has been moved into the `bin` directory on v2. You may need to adjust your `$PATH` accordingly._ + +## v1 (and prior) + New as of v0.2 is that dependencies are managed via [Composer](https://getcomposer.org/), most notably it has been rebuilt on top of Symfony's Console component to provide a more feature-packed base to build from. [Follow these instructions if you haven't installed Composer before](https://getcomposer.org/doc/00-intro.md) To get started with Gitify, it's easiest to set up a local clone of this repository. It doesn't matter in which folder clone it to. On Unix/Linux systems you can choose your home directory. After that, run Composer to download the dependencies, and finally make the Gitify file executable to run it. ```` -$ git clone https://github.com/modmore/Gitify.git Gitify -$ cd Gitify +git clone https://github.com/modmore/Gitify.git Gitify +cd Gitify # If you haven't installed composer, yet, you can do this to install the composer.phar: # curl -sS https://getcomposer.org/installer | php -$ composer install (or php composer.phar install) -$ chmod +x Gitify +composer install --no-dev +# or: php composer.phar install --no-dev +chmod +x Gitify ```` At this point you should be able to type `./Gitify` and get a response like the following: @@ -34,7 +70,7 @@ install install:modx Downloads, configures and installs a fresh MODX installation. ```` -If that's working as expected, the next step is to add the Gitify executable to your PATH so you can run Gitify in any directory. Edit your `~/.bash_profile` and add the following, with the right path to the Gitify directory (not file) of course: +If that's working as expected, the next step is to add the Gitify executable to your PATH so you can run Gitify in any directory. Edit your `~/.bash_profile`, `~/.zshrc` or `~/.profile` file and add the following, with the right path to the Gitify **directory** (not the executable file): ```` export PATH=/path/to/Gitify/:$PATH diff --git a/en/50_Open_Source/Gitify/02_Commands/01_Build.md b/en/50_Open_Source/Gitify/02_Commands/01_Build.md index afba96e3..080a12c0 100644 --- a/en/50_Open_Source/Gitify/02_Commands/01_Build.md +++ b/en/50_Open_Source/Gitify/02_Commands/01_Build.md @@ -8,13 +8,15 @@ Also as of v0.9, `Gitify build` automatically tries to resolve duplicate id/prim ```` Usage: - build [--skip-clear-cache] [-f|--force] [--no-backup] + build [--skip-clear-cache] [-f|--force] [--no-backup] [--no-cleanup] Options: --skip-clear-cache When specified, it will skip clearing the cache after building. --force (-f) When specified, all existing content will be removed before rebuilding. Can be useful when having dealt with complex conflicts. --no-backup When using the --force attribute, Gitify will automatically create a full database backup first. Specify --no-backup to skip creating the backup, at your own risk. + --no-cleanup With --no-cleanup specified the built-in orphan handling is disabled for this build. The orphan handling removes objects that no longer exist in files from the database. --help (-h) Display this help message. --verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug. --version (-V) Display the Gitify version. + --dotfile=.filename Gitify YAML file to use. ```` diff --git a/en/50_Open_Source/Gitify/02_Commands/02_Extract.md b/en/50_Open_Source/Gitify/02_Commands/02_Extract.md index f5fe8e37..b5e81650 100644 --- a/en/50_Open_Source/Gitify/02_Commands/02_Extract.md +++ b/en/50_Open_Source/Gitify/02_Commands/02_Extract.md @@ -10,6 +10,7 @@ Options: --help (-h) Display this help message. --verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug. --version (-V) Display the Gitify version. + --dotfile=.filename Gitify YAML file to use. ```` To give an example of the YAML data file, here's how a plugin would be stored: diff --git a/en/50_Open_Source/Gitify/02_Commands/08_Package_Install.md b/en/50_Open_Source/Gitify/02_Commands/08_Package_Install.md index 52603012..437bae18 100644 --- a/en/50_Open_Source/Gitify/02_Commands/08_Package_Install.md +++ b/en/50_Open_Source/Gitify/02_Commands/08_Package_Install.md @@ -19,5 +19,5 @@ Options: --help (-h) Display this help message. --verbose (-v|vv|vvv) Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug. --version (-V) Display the Gitify version. - + --packages (-p) Skip extracting installed packages when set. ```` \ No newline at end of file diff --git a/en/50_Open_Source/Gitify/03_dot-gitify.md b/en/50_Open_Source/Gitify/03_dot-gitify.md index 6ad521d4..531273fc 100644 --- a/en/50_Open_Source/Gitify/03_dot-gitify.md +++ b/en/50_Open_Source/Gitify/03_dot-gitify.md @@ -4,11 +4,18 @@ title: .gitify file To define what to export, to where and how, we're using a `.gitify` file formatted in YAML. This file is located in the root of the project. + +_As of Gitify v2.0.1-pl, it's possible to specify a different YAML config file to use with the `--dotfile` option, when used with the `build` or `extract` commands._ +``` +gitify extract --dotfile=.myconfigfile +``` + An example `.gitify` may look like this: ```` data_directory: _data/ backup_directory: _backup/ +category_ids_in_elements: true data: contexts: class: modContext @@ -144,6 +151,21 @@ data: As it'll load the package into memory, it's only required to add the package once. For clarify, it can't hurt to add it to each `data` entry that uses it. +As of Gitify 2.1.0-pl, support has been added for the xPDO v3 model structure. [Collections](https://docs.modx.com/3.x/en/extras/collections/index) is one extra that uses the new model structure when installed in MODX 3. + +An example of how to specify the `CollectionSetting` object in the `.gitify` file would be: + +```` + collections_settings: + namespace: Collections + model: Collections\Model + class: Collections\Model\CollectionSetting + primary: id + package: collections +```` + +Note that while the `primary` and `package` fields are the same as the 2.x structure, `class` now uses the fully qualified class name. + ### Dealing with Closures A Closure is a separate table in the database that a core or third party extra may use to keep information about a hierarchy in a convenient format. These are often automatically generated when creating a new object, which can result in a error messages and other issues when building, especially with the `--force` flag. @@ -211,4 +233,8 @@ Alternatively, you can also define the username and api_key directly on the prov For security, the key file needs to be kept out of the git repository using a .gitignore file, and you will also want to protect direct read access to it with your .htaccess file or keeping it out of the webroot. -To install the packages that you added to the `packages` entry in the .gitify file, simply run the command `Gitify package:install --all`. That will attempt to install all packages that were mentioned, skipping any that are already installed. \ No newline at end of file +To install the packages that you added to the `packages` entry in the .gitify file, simply run the command `Gitify package:install --all`. That will attempt to install all packages that were mentioned, skipping any that are already installed. + +### Category ids in elements + +By default, Gitify refers to an element category by its name field. If you experience issues where categories might have identical names, add `category_ids_in_elements: true` to your `.gitify` file, and categories will instead by specified by their `id`. diff --git a/en/50_Open_Source/Gitify/06_Examples.md b/en/50_Open_Source/Gitify/06_Examples.md index f8ea58fd..3268fe2a 100644 --- a/en/50_Open_Source/Gitify/06_Examples.md +++ b/en/50_Open_Source/Gitify/06_Examples.md @@ -207,12 +207,19 @@ data: class: cbField primary: [id, name] package: contentblocks + cb_categories: + class: cbCategory + primary: [id, name] cb_layouts: class: cbLayout primary: [id, name] cb_templates: class: cbTemplate primary: [id, name] + cb_defaults: + class: cbDefault + primary: id + redirects: class: modRedirect primary: id @@ -278,4 +285,108 @@ data: migx_config: class: migxConfig primary: [id, name] -```` \ No newline at end of file +```` + +## Including objects when package uses a service-class + +If an extra uses a service-class instead of a normal class (like Commerce does), +then the name of the service has to be provided at the first config-object with the *service* option. + +```` + commerce_currency: + class: comCurrency + primary: id + package: commerce + service: Commerce + commerce_product: + class: comProduct + primary: id + commerce_product_bundle_product: + class: comProductBundleProduct + primary: id + commerce_order: + class: comOrder + exclude_keys: + - created_on + primary: id + commerce_order_item: + class: comOrderItem + primary: id + commerce_order_shipment: + class: comOrderShipment + primary: id + commerce_delivery_type: + class: comDeliveryType + primary: id + commerce_shipping_method: + class: comShippingMethod + primary: id + commerce_status: + class: comStatus + primary: id + commerce_status_change: + class: comStatusChange + primary: id + commerce_status_change_action: + class: comStatusChangeAction + primary: id + commerce_tax_group: + class: comTaxGroup + primary: id + commerce_tax_rule: + class: comTaxRule + primary: id + commerce_tax_rate: + class: comTaxRate + primary: id + commerce_order_item_tax_rate: + class: comOrderItemTax + primary: id + commerce_order_item_adjustment: + class: comOrderItemAdjustment + primary: id + commerce_order_log: + class: comOrderLog + primary: id + commerce_order_address: + class: comOrderAddress + primary: id + commerce_address: + class: comAddress + primary: id + commerce_order_message: + class: comOrderMessage + primary: id + exclude_keys: + - created_on + commerce_transaction: + class: comTransaction + primary: id + commerce_payment_method: + class: comPaymentMethod + primary: id + commerce_module: + class: comModule + primary: id + commerce_coupon: + class: comCoupon + primary: id + commerce_coupon_usage: + class: comCouponUsage + primary: id +```` + +### Duplicate a context and resources + +As of Gitify 2.1.0-pl it is possible to duplicate a context with all its resources under a new key. +This is especially handy for adding a new language translation to an existing site quickly. +To do so, extract a single context that you wish to have duplicated, copy the output and run the extracted content through your favourite translation tool. + +Then: + + - Change the `context_key` in your `.gitify` file to the new context key. + - Rename the extracted files and folders + - Do a find and replace to update all instances of the `context_key` within the extracted content + - Finally, run `gitify build` to import the updated data as the new context. + +[You can see a video from the author of this feature here.](https://github.com/modmore/Gitify/pull/439) diff --git a/en/50_Open_Source/Gitify/07_Installing_a_Gitify_Project.md b/en/50_Open_Source/Gitify/07_Installing_a_Gitify_Project.md index 3a39c7a7..d15ea535 100644 --- a/en/50_Open_Source/Gitify/07_Installing_a_Gitify_Project.md +++ b/en/50_Open_Source/Gitify/07_Installing_a_Gitify_Project.md @@ -21,7 +21,7 @@ Now open `.gitify` and configure it to your liking. If you are using a custom re ## Installing MODX Now we are ready to tell gitify to install the latest MODX and all needed packages: - Gitify install:modx + Gitify modx:install After you've used this command Gitify will ask you some questions, if you didn't create a database yet you can put in the details of a MySQL user who has the rights to create databases. The result should look like this: @@ -47,7 +47,7 @@ The result should look like this: MODX has now been freshly installed and is now ready to have extras installed. But installing them one by one is going to be a hassle so we're just gonna execute this command: - Gitify install:package --all + Gitify package:install --all This command installs all the packages defined in `.gitify`, the result should look something like this: diff --git a/en/50_Open_Source/Gitify/index.md b/en/50_Open_Source/Gitify/index.md index 4ae21a62..8dd1b9e9 100644 --- a/en/50_Open_Source/Gitify/index.md +++ b/en/50_Open_Source/Gitify/index.md @@ -2,6 +2,6 @@ The project configuration, which determines what data is written to file and build to the database, is stored in a [.gitify file](dot-gitify) in the project root. -[Gitify Watch](https://www.modmore.com/gitifywatch/) is a free companion MODX Extra for Gitify, which will automatically extract information from MODX when changes are made. +[Gitify Watch](https://modmore.com/gitifywatch/) is a free companion MODX Extra for Gitify, which will automatically extract information from MODX when changes are made. Gitify was first introduced at the MODX Weekend 2014. [A video of that talk is available here](https://video.modmore.com/modx-weekend-2014/sunday-backend/staging-workflow-with-git-and-gitify/). [Slides of the MODXpo 2015 talk can be found here](http://www.slideshare.net/hamstramark1/dev-staging-production-workflow-with-gitify-at-modxpo-2015-in-munich), which walks you through the purpose of Gitify and how the process can be set up. \ No newline at end of file diff --git a/en/50_Open_Source/GitifyWatch/01_Getting_Started.md b/en/50_Open_Source/GitifyWatch/01_Getting_Started.md index 47c34c66..4b3a5723 100644 --- a/en/50_Open_Source/GitifyWatch/01_Getting_Started.md +++ b/en/50_Open_Source/GitifyWatch/01_Getting_Started.md @@ -9,7 +9,7 @@ Gitify Watch is primarily meant for use on staging or production environments wh These are the steps needed to set up Gitify Watch, which are explained in a bit more detail if you follow the link: 1. [Download and install Scheduler](../Scheduler/Installation) in MODX (and [install Gitify on your server](../Gitify/Installation) if it isn't there yet) -2. [Download and install Gitify Watch](https://www.modmore.com/gitifywatch/download/) +2. [Download and install Gitify Watch](https://modmore.com/gitifywatch/download/) 3. [Point Gitify Watch to your Gitify installation](Link_Gitify) 4. [Configure your environments in the .gitify file](Configure_Environments) 5. [Make sure the git repository is set up properly](Repository_Setup) diff --git a/en/50_Open_Source/GoogleDrive/index.md b/en/50_Open_Source/GoogleDrive/index.md new file mode 100644 index 00000000..aebdd3f8 --- /dev/null +++ b/en/50_Open_Source/GoogleDrive/index.md @@ -0,0 +1,100 @@ +--- +title: Google Drive Media Source +--- + +_Special thanks to [Catch Media](https://catchmedia.no) for commissioning this extra._ + +This package includes a MODX Media Source implementation to provide access and standard file management features for Google Drive from within MODX. + +The media source requires MODX 3.0+ and PHP 8.0+. + +[TOC] + +## Set-up + +There are a few steps to get up and running with Google Drive. + +### 1. Installation + +First **install the transport package**, available from MODX.com or [from GitHub](https://github.com/modmore/GoogleDriveMediaSource/tree/main/_packages). + +Go to Media > Media Sources and create a new media source, selecting Google Drive as the source type. + +### 2. Credentials + +[Follow these instructions to create a Client ID and Client Secret](https://github.com/ivanvermeyen/laravel-google-drive-demo/blob/master/README/1-getting-your-dlient-id-and-secret.md). + +Set the **Authorized Redirect URIs** to the **full link to the edit media source page in your MODX Manager**, including the action and ID. For example: `https://yoursite.com/manager/?a=source/update&id=2`. You can add multiple allowed redirect URIs. + +After that, return to the media source edit page and **expand the description for the `refreshToken` property to make the authorization button visible. + +![Screenshot of the refresh token property](refresh-token.jpg) + +Click the button and login with your Google account. Note that the Drive integration will inherit the users' permissions, so it may be important to choose who will authorize the integration wisely. + +> If you receive the error "Access blocked: Google Drive Media Source’s request is invalid" with "Error 400: redirect_uri_mismatch", you've made a mistake in setting up the redirect URI in the Google Console. Expand the error message details to see the exact redirect URI that was attempted, and copy/paste that into the Google Console. + +After returning from Google, the refreshToken will be filled for you. + +### 3. Configuration + +Now you can choose the **root** for the media source. + +The root can be: + +- The root of your (user) Drive by selecting the first option, `- root -`. +- A specific folder in the root of your Drive, and its subfolders. It's not possible to select a directory that is NOT itself in the root as root for the media source. +- A Shared Drive, previously known as Team Drive. +- A shortcut located in the root of the user's drive, pointing to a folder elsewhere. + +Simply select the desired root in the list, save again. + +You can also set the **maxItemsPerLevel** option. This can be set to a value up to 1000 to indicate the maximum number of files or directories to appear on a specific level. The default, 250, is a reasonable trade-off between performance and usability. + +### 4. Friendlier URLs + +The **urlPattern** lets you configure a friendly URL to the files. All files in the Drive media source are referenced **by their ID** rather than their name. + +The default urlPattern, `/assets/components/googledrivemediasource/?s={source}&id={id}`, lets you use the media source with no changes, but results in pretty ugly URLs, while also exposing you use Google Drive. It can also cause compatibility issues with some extras. + +It is recommended to configure a rewrite for Apache: + +``` +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule ^drive/(.+)$ /assets/components/googledrivemediasource/index.php?s=2&id=$1 [L,QSA] +# change the ID here if needed ^^^ +``` + +Or for nginx (MODX Cloud): + +```nginx +rewrite ^/drive/(.*)$ /assets/components/googledrivemediasource/index.php?s=2&id=$1 last; +# change the ID here if needed ^^^ +# put before the location block +#location / { +# try_files $uri $uri/ @modx-rewrite; +#} +``` + +The s=2 parameter indicates the **media source ID**, in this example ID 2. Change that as needed. + +The **urlPattern** in the media source can then drop the media source ID and be configured to: + +```html +https://yoursite.com/drive/{id} +``` + +> **You should run this proxy with a fully qualified URL in the urlPattern, to maximise compatibility with third party tools**. This could be on a (sub)domain, but has to start with https. Make sure all requests are routed to the index file and that the `s` and `id` parameters are properly set from the request or rewrite. + +> For phpthumb and the MODX media browser, it is necessary to set the `phpthumb_nohotlink_enabled` system setting to `No` to see thumbnails. This allows it to handle external files that are not replicated on the local file system. + +## Integrations + +When using the media source with other extras, you may run into compatibility issues because files and directories are referenced by IDs and cannot be found on the local file system. + +We've confirmed the MODX core, Image+, ContentBlocks, and phpthumb, **however you will need to run the friendly URLs proxy from a (sub)domain with a full https url configured**. Otherwise, they may try to find the file locally, where it will be unable of finding any files. + +Please do report any incompatibilities **when using a full url** [on GitHub](https://github.com/modmore/GoogleDriveMediaSource/issues). + + diff --git a/en/50_Open_Source/GoogleDrive/refresh-token.jpg b/en/50_Open_Source/GoogleDrive/refresh-token.jpg new file mode 100644 index 00000000..58f34c5c Binary files /dev/null and b/en/50_Open_Source/GoogleDrive/refresh-token.jpg differ diff --git a/en/50_Open_Source/QuickstartButtons/index.md b/en/50_Open_Source/QuickstartButtons/index.md index c79185a6..84f8bdae 100644 --- a/en/50_Open_Source/QuickstartButtons/index.md +++ b/en/50_Open_Source/QuickstartButtons/index.md @@ -1,8 +1,8 @@ -Based on an idea by Christian Seel, the free [Quickstart Buttons](https://www.modmore.com/extras/quickstartbuttons/) package allows you to manage big buttons that show up on the MODX Manager Dashboard. +Based on an idea by Christian Seel, the free [Quickstart Buttons](https://modmore.com/extras/quickstartbuttons/) package allows you to manage big buttons that show up on the MODX Manager Dashboard. ## Getting Started -1. [Install the package](https://www.modmore.com/extras/quickstartbuttons/download/) +1. [Install the package](https://modmore.com/extras/quickstartbuttons/download/) 2. Refresh the page so the top menu is updated. 3. Find Quickstart Buttons in the menu under Extras / Components 4. Edit the buttons set to add/edit items. diff --git a/en/50_Open_Source/Scheduler/01_Installation.md b/en/50_Open_Source/Scheduler/01_Installation.md index 4ffdb5a8..c7ce0f66 100644 --- a/en/50_Open_Source/Scheduler/01_Installation.md +++ b/en/50_Open_Source/Scheduler/01_Installation.md @@ -2,7 +2,7 @@ Scheduler can be installed from the modmore.com package provider, as well as via ## Install the Package -Using the modmore.com [Package Provider](https://www.modmore.com/about/package-provider/) you can install the Scheduler package super easily. Please see the [full instructions for the package install](https://www.modmore.com/extras/scheduler/download/) for more details. +Using the modmore.com [Package Provider](https://modmore.com/about/package-provider/) you can install the Scheduler package super easily. Please see the [full instructions for the package install](https://modmore.com/extras/scheduler/download/) for more details. ## Installing from Git @@ -27,8 +27,14 @@ By default Scheduler only runs one task each time it is triggered. You can chang How to set up the cron job depends on your server, but the command you will want to add is the following: -```` html -php -q /home/server\_user/path/to/assets/components/scheduler/run.php +```` html +php -q /home/server\_user/path/to/assets/components/scheduler/run.php ```` -If you use an external cron job service, simply point it to `assets/components/scheduler/run.php` file. +### External Crons + +If you use an external cron job service that triggers the file with a HTTP request, point it to `https://yoursite.com/assets/components/scheduler/run.php?ctx=web` - including the `&ctx` URL parameter. + +> Running cron jobs over HTTP is not recommended. It means a front-end web server is processing the request, which are practically always configured with limits on memory and processing times, which can cause long or heavy tasks to fail. +> +> These limits are not in place for actual CRON jobs on the server. diff --git a/en/50_Open_Source/Scheduler/03_Scheduling_a_Task.md b/en/50_Open_Source/Scheduler/03_Scheduling_a_Task.md index bc3289c2..93f188cd 100644 --- a/en/50_Open_Source/Scheduler/03_Scheduling_a_Task.md +++ b/en/50_Open_Source/Scheduler/03_Scheduling_a_Task.md @@ -18,7 +18,7 @@ if (!($scheduler instanceof Scheduler)) { */ $task = $scheduler->getTask('mycmp', 'dosomething'); if ($task instanceof sTask) { - // Schedule a run in 10 minutes from no + // Schedule a run in 10 minutes from now // We're passing along an array of data; in this case a client ID. $task->schedule('+10 minutes', array( 'client' => 15 diff --git a/en/50_Open_Source/Scheduler/index.md b/en/50_Open_Source/Scheduler/index.md index 5074fe2b..d41035b4 100644 --- a/en/50_Open_Source/Scheduler/index.md +++ b/en/50_Open_Source/Scheduler/index.md @@ -1 +1,11 @@ -[Scheduler](https://www.modmore.com/extras/scheduler/) is an open source (MIT) Extra for MODX Revolution that handles scheduling tasks in the future and other automation. It is meant to provide an easy to integrate and administer scheduling engine or message queue for developers, with a component for admins. +[Scheduler](https://modmore.com/extras/scheduler/) is an open source (MIT) Extra for MODX Revolution that handles scheduling tasks in the future and other automation. It is meant to provide an easy to integrate and administer scheduling engine or message queue for developers, with a component for admins. + +## Configuration + +First and foremost, you [will need to setup a cron job](Installation) to make sure Scheduler gets triggered every minute. + +You also have a few settings at your disposal: + +1. Set up email notifications for tasks that fail. Set a comma separated list of email addresses in the `scheduler.email_failure` system setting. +2. Automatically remove old tasks after a certain time period has passed. Useful to keep your database size under control if you schedule a lot of tasks. To do this, set a strtotime() compatible time string in the `scheduler.delete_tasks_after` system setting. For example set it to `-1 year` or `-2 weeks`. Remember the dash. This will run automatically from the same cron jon as the actual tasks. (v1.3+). + diff --git a/en/50_Open_Source/SimpleAB/01_Testing_Templates.md b/en/50_Open_Source/SimpleAB/01_Testing_Templates.md index 6d852956..682d738c 100644 --- a/en/50_Open_Source/SimpleAB/01_Testing_Templates.md +++ b/en/50_Open_Source/SimpleAB/01_Testing_Templates.md @@ -105,6 +105,6 @@ You'll need to log conversions if you want to calculate a conversion rate, so le #### 8. Let data pour in... -Now it's the time to get a refill for that empty cup. Depending on how many visits your site gets, it may take a few hours to a few weeks to get some reliable data. Sounds like a great time to pick up a new hobby, or to write about how awesome SimpleAB is on your blog and earn money with our [Affiliate program](https://www.modmore.com/account/affiliate/). :) +Now it's the time to get a refill for that empty cup. Depending on how many visits your site gets, it may take a few hours to a few weeks to get some reliable data. Sounds like a great time to pick up a new hobby, or to write about how awesome SimpleAB is on your blog and earn money with our [Affiliate program](https://modmore.com/account/affiliate/). :) We take documentation serious, and we hope this tutorial has helped you understanding creating Template Tests with SimpleAB. If you need more help which is not covered here, or spot any issues, please don't hesitate to [get in touch with support](https://support.modmore.com/) and we'd be glad to help. diff --git a/en/50_Open_Source/SimpleAB/06_Tips_tricks.md b/en/50_Open_Source/SimpleAB/06_Tips_tricks.md index f80de742..7a768daa 100644 --- a/en/50_Open_Source/SimpleAB/06_Tips_tricks.md +++ b/en/50_Open_Source/SimpleAB/06_Tips_tricks.md @@ -33,4 +33,4 @@ When a user is not an Admin, only report functionalities are available in the co ### [Hide mod**more** Logo](#logo) -At the bottom right of the component, we display the mod**more** logo by default, with a link to the [SimpleAB Documentation](https://www.modmore.com/extras/simpleab/documentation/), because we want you to remember us while you deliver awesomeness to your client. Are we stuck in your brain already? Great! Head over to _System_ » _System Settings_ and choose _simpleab_ in the namespace dropdown (the one that defaults to core), and set `simpleab.hide_logo` to _yes_. \ No newline at end of file +At the bottom right of the component, we display the mod**more** logo by default, with a link to the [SimpleAB Documentation](https://modmore.com/extras/simpleab/documentation/), because we want you to remember us while you deliver awesomeness to your client. Are we stuck in your brain already? Great! Head over to _System_ » _System Settings_ and choose _simpleab_ in the namespace dropdown (the one that defaults to core), and set `simpleab.hide_logo` to _yes_. \ No newline at end of file diff --git a/en/50_Open_Source/SimpleAB/index.md b/en/50_Open_Source/SimpleAB/index.md index cc584784..bfc589fe 100644 --- a/en/50_Open_Source/SimpleAB/index.md +++ b/en/50_Open_Source/SimpleAB/index.md @@ -1,4 +1,4 @@ -[SimpleAB](https://www.modmore.com/extras/simpleab/) is a tool that allows you to perform A/B tests on chunks and templates in MODX. This is used when trying to improve conversions, to see the impact of specific changes. +[SimpleAB](https://modmore.com/extras/simpleab/) is a tool that allows you to perform A/B tests on chunks and templates in MODX. This is used when trying to improve conversions, to see the impact of specific changes. -SimpleAB was originally a Premium Extra, but [was made free in August 2016](https://www.modmore.com/blog/2016/simpleab-free/). +SimpleAB was originally a Premium Extra, but [was made free in August 2016](https://modmore.com/blog/2016/simpleab-free/). diff --git a/en/50_Open_Source/index.md b/en/50_Open_Source/index.md new file mode 100644 index 00000000..3b13eafc --- /dev/null +++ b/en/50_Open_Source/index.md @@ -0,0 +1,19 @@ +--- +title: Open Source Extras +--- + +We build and maintain many open source extras. You'll find the following documentation here: + +- [Akismet](Akismet) +- [BigBrother](BigBrother) +- [ClientConfig](ClientConfig) +- [Dashbored](Dashbored) +- [Gitify](Gitify) +- [GitifyWatch](GitifyWatch) +- [Google Drive Media Source](GoogleDrive) +- [Quickstart Buttons](QuickstartButtons) +- [Scheduler](Scheduler) +- [SimpleAB](SimpleAB) + +Please note that our standard email support is only available for Premium Extras. For help with our open source extras, please [post on our community forum](https://forum.modmore.com/c/open-source/12), or ask about our Premium Support options. + diff --git a/en/99_Meta/00_About_modmore.md b/en/99_Meta/00_About_modmore.md index 1d4feb73..19e7b3af 100644 --- a/en/99_Meta/00_About_modmore.md +++ b/en/99_Meta/00_About_modmore.md @@ -1,3 +1,3 @@ -[modmore](https://www.modmore.com/) provides extras and services for MODX Revolution. It was founded by Mark Hamstra in July 2013. +[modmore](https://modmore.com/) provides extras and services for MODX Revolution. It was founded by Mark Hamstra in July 2013. In this part of the documentation you can learn more about other aspects of modmore that are not specifically about any particular extra. diff --git a/en/99_Meta/01_Package_Provider.md b/en/99_Meta/01_Package_Provider.md index b713aaca..33f89a80 100644 --- a/en/99_Meta/01_Package_Provider.md +++ b/en/99_Meta/01_Package_Provider.md @@ -1,13 +1,13 @@ To install the extras from modmore you need to configure a new Package Provider in your MODX installation. This will allow you to download, install and update our extras from within MODX. -For our Premium Extras you will first need to purchase a license, or a [development domain to use a free development license](https://www.modmore.com/free-development-licenses/). +For our Premium Extras you will first need to purchase a license, or a [development domain to use a free development license](https://modmore.com/free-development-licenses/). [TOC] ## Step 1: Create an API Key -To connect with our Package Provider, you first need to create an API Key. This is done on our website under [Account » API Keys](https://www.modmore.com/account/api-keys/). +To connect with our Package Provider, you first need to create an API Key. This is done on our website under [Account » API Keys](https://modmore.com/account/api-keys/). API Keys act as a username and password for the webservices, and is connected to your account. @@ -31,7 +31,7 @@ To browse and download our extras, click on the small arrow on the _Download Ext At this point you should see the start screen of the provider, with a list of most popular and latest updated extras from our provider. You can click one of the extras on that screen to search for it, or you can use the left hand tree view to browse by category. -If you're on a domain that's eligible for a [free development license](https://www.modmore.com/free-development-licenses/), our premium extras will say "Free to try on development" in the name and a download will not require or deduct any available licenses. +If you're on a domain that's eligible for a [free development license](https://modmore.com/free-development-licenses/), our premium extras will say "Free to try on development" in the name and a download will not require or deduct any available licenses. ## Step 3: Download & Install diff --git a/en/index.md b/en/index.md index 302e942d..b3efbf6d 100644 --- a/en/index.md +++ b/en/index.md @@ -4,21 +4,65 @@ title: Official modmore documentation # Welcome to the modmore documentation -If you're looking for information on using the [Premium Extras from modmore](https://www.modmore.com/extras/), look no further! On this shiny new documentation site, you can read more about how our products work, and what you can make with them. - -The navigation on the side allows you to browse the documentation hierarchically. The search at the top is useful if you already know what you're looking for. If you're actually reading _everything_, there's previous and next links at the bottom of the page. +If you're looking for information on using our [Extras for MODX](https://modmore.com/extras/), look no further! All documentation for extras developed or distributed by modmore can be found on this site. ## Get help -If you still have questions, let us know via support@modmore.com or [post on our community forum](https://forum.modmore.com/). We're here to help! +If you can't find the answer to your question in the documentation, it's worth checking the [frequently asked questions](https://support.modmore.com). The most common questions are collected there, often linking back to detailed documentation here. + +To get in touch, email support@modmore.com or [post on our community forum](https://forum.modmore.com/). We're here to help! + +## Available extras & support + +Depending on the extra, different levels of support are available. + +- For **open source extras**, [post on our forum](https://forum.modmore.com/c/open-source/12) or the [MODX community forum](https://community.modx.com/) to get help. Or if you need help quickly, get paid [Premium Support](https://modmore.com/premium-modx-support/). +- For **premium extras**, email support is included with your license, and is provided by modmore or Treehill Studio. If you email [support@modmore.com](mailto:support@modmore.com) it'll land in the right inbox, and you'll get a response within 24 hours (business days). + +For third party extras (other than those by Treehill Studio), we offer paid [Premium Support](https://modmore.com/premium-modx-support/). + +Here's a summary of the extras currently available from modmore and their support options/information links: + +| Extra | Provided support | | +|------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------|--------------------------------------------------------------------------:| +| [Agenda](Agenda) | Email (Treehill Studio) | [About Agenda](https://modmore.com/agenda/) | +| [Akismet](Open_Source/Akismet) | Forum / [Premium Support](https://modmore.com/premium-modx-support/) | [About Akismet](https://modmore.com/extras/akismet/) | +| [BabelTranslate](BabelTranslate) | Email (Treehill Studio) | [About BabelTranslate](https://modmore.com/babeltranslate/) | +| [Big Brother](Open_Source/BigBrother) | Forum / [Premium Support](https://modmore.com/premium-modx-support/) | [About Big Brother](https://modmore.com/extras/bigbrother/) | +| [ClientConfig](Open_Source/ClientConfig) | Forum / [Premium Support](https://modmore.com/premium-modx-support/) | [About ClientConfig](https://modmore.com/extras/clientconfig/) | +| [Commerce](Commerce), including core modules and [official extensions listed here](https://modmore.com/commerce/extensions/) | Email (modmore) | [About Commerce](https://modmore.com/commerce/) | +| [ConsentFriend](ConsentFriend) | Email (Treehill Studio) | [About ConsentFriend](https://modmore.com/consentfriend/) | +| [ContentBlocks](ContentBlocks) | Email (modmore) | [About ContentBlocks](https://modmore.com/contentblocks/) | +| [CSRF Helper](Open_Source/CSRFHelper) | Forum / [Premium Support](https://modmore.com/premium-modx-support/) | [About CSRF Helper](https://modmore.com/extras/csrfhelper/) | +| [Cursus](https://docs.treehillstudio.de/en/cursus/) | Email (Treehill Studio) | [About Cursus](https://modmore.com/cursus/) | +| DailyPhoto | Forum / [Premium Support](https://modmore.com/premium-modx-support/) | [About DailyPhoto](https://modmore.com/extras/dailyphoto/) | +| Dashbored | Forum / [Premium Support](https://modmore.com/premium-modx-support/) | [About Dashbored](https://modmore.com/extras/dashbored/) | +| [Gitify](Open_Source/Gitify) | Forum / [Premium Support](https://modmore.com/premium-modx-support/) | [About Gitify](https://github.com/modmore/Gitify#readme) | +| [GitifyWatch](Open_Source/GitifyWatch) | Forum / [Premium Support](https://modmore.com/premium-modx-support/) | [About GitifyWatch](https://modmore.com/gitifywatch/) | +| [Google Drive](Open_Source/GoogleDrive) | Forum / [Premium Support](https://modmore.com/premium-modx-support/) | [About Google Drive](https://modmore.com/extras/googledrive/) | +| MagicPreview | Forum / [Premium Support](https://modmore.com/premium-modx-support/) | [About MagicPreview](https://modmore.com/extras/magicpreview/) | +| [MoreGallery](MoreGallery) | Email (modmore) | [About MoreGallery](https://modmore.com/moregallery/) | +| [Quickstart Buttons](Open_Source/QuickstartButtons) | Forum / [Premium Support](https://modmore.com/premium-modx-support/) | [About Quickstart Buttons](https://modmore.com/extras/quickstartbuttons/) | +| [Redactor](Redactor) | Email (modmore) | [About Redactor](https://modmore.com/redactor/) | +| [Scheduler](Open_Source/Scheduler) | Forum / [Premium Support](https://modmore.com/premium-modx-support/) | [About Scheduler](https://modmore.com/extras/scheduler/) | +| [SimpleAB](Open_Source/SimpleAB) | Forum / [Premium Support](https://modmore.com/premium-modx-support/) | [About SimpleAB](https://modmore.com/extras/simpleab/) | +| [SimpleCart](SimpleCart) | Email (modmore) | [About SimpleCart](https://modmore.com/simplecart/) | +| SiteDash Client | Email (modmore) | [About SiteDash](https://modmore.com/extras/sitedashclient/) | + +Additionally, documentation is available for several extras by Sterc. These extras were offered as premium before, but were open sourced as the provided support level was insufficient. These extras are no longer available from modmore, but we've kept the documentation around as they are currently the only copy. + +- [DigitalSignage](DigitalSignage) +- [Formalicious](Formalicious) + +> **These extras are not covered by modmore's standard support.** If you need help with them, we offer paid [Premium Support](https://modmore.com/premium-modx-support/) or you may reach out to Sterc directly/on GitHub. ## Browse the documentation offline -It's possible to [download a full archive of this website](modmore-documentation.zip) (around 6MB) to browse it offline. After downloading, unpack the zip file into a memorable place. +It's possible to [download a full archive of this website](modmore-documentation.zip) (around 25MB) to browse it offline. After downloading, unpack the zip file into a memorable place. -You'll get the best results when serving the files on a local web server (apache/nginx). This will allow you to use the entire documentation site exactly like it works on [docs.modmore.com](https://docs.modmore.com/), including a functional search. +You'll get the best results when serving the files on a local web server (apache/nginx). This will allow you to use the entire documentation site exactly like it works on [docs.modmore.com](https://docs.modmore.com/), including a functional search. -**Note**: Not all images are included in the download. This means that if you're actually offline you might not see relevant screenshots. +> Not all images are included in the download. If you're actually offline you might not see all screenshots. ## Improve the documentation diff --git a/index.md b/index.md index 450562aa..6c54a83a 100644 --- a/index.md +++ b/index.md @@ -1,3 +1,5 @@ -Welcome to the modmore documentation! Please choose a language. +Welcome to the modmore documentation! Please choose a language. -- [English](en/index) \ No newline at end of file +- [English](en/index) + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..3715a283 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,4444 @@ +{ + "name": "docs.modmore.com", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "docs.modmore.com", + "version": "1.0.0", + "devDependencies": { + "bower": "1.x.x", + "esprima": "^3.1.0", + "jshint": "latest", + "live-reload": "1.x.x", + "mkdirp": "^0.5.1", + "parallelshell": "2.0.x", + "rimraf": "latest", + "sass": "^1.32.8", + "svg-sprite": "1.0.x", + "watch": "0.x.x" + } + }, + "node_modules/ansi-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", + "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "node_modules/assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "node_modules/aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/backoff": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/backoff/-/backoff-1.0.0.tgz", + "integrity": "sha1-AJgveBWOxtA/mWk+wPtfeyrR4o4=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/bal-util": { + "version": "1.13.13", + "resolved": "https://registry.npmjs.org/bal-util/-/bal-util-1.13.13.tgz", + "integrity": "sha1-YyxJUgo2fsWqhUaI4Qgn2bUZMl8=", + "dev": true, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/Base64": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.1.4.tgz", + "integrity": "sha1-6fbGvvVn/WNepBYqsU3TKedKpt4=", + "dev": true + }, + "node_modules/base64-js": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.2.tgz", + "integrity": "sha1-Ak8Pcq+iW3X5wO5zzU9V7Bvtl4Q=", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz", + "integrity": "sha1-PKdrhSQccXC/fZcD57mqdGMAQNQ=", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.0.3.tgz", + "integrity": "sha512-phbvN+yOk05EGoFcV/0S8N8ShnJqf6VCWRAw5he2gvRwBubFt/OzmcTNGqBt5b7Y4RK3YCgf6jrgGSR0Cwtsgw==", + "dev": true, + "dependencies": { + "readable-stream": "~2.0.5" + } + }, + "node_modules/bl/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha512-KbiZEa9/vofNcVJXGwdWWn25reQ3V3dHBWbS07FTF3/TOehLnm9GEhJV4T6ZvGPkShRpmUqYwnaCrkj0mRnP6Q==", + "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", + "dev": true, + "dependencies": { + "hoek": "2.x.x" + }, + "engines": { + "node": ">=0.10.40" + } + }, + "node_modules/bops": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/bops/-/bops-0.0.6.tgz", + "integrity": "sha1-CC0dVfoB5g29wuvC26N/ZZVUzzo=", + "dev": true, + "dependencies": { + "base64-js": "0.0.2", + "to-utf8": "0.0.1" + } + }, + "node_modules/bower": { + "version": "1.8.14", + "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.14.tgz", + "integrity": "sha512-8Rq058FD91q9Nwthyhw0la9fzpBz0iwZTrt51LWl+w+PnJgZk9J+5wp3nibsJcIUPglMYXr4NRBaR+TUj0OkBQ==", + "dev": true, + "bin": { + "bower": "bin/bower" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserify": { + "version": "1.16.8", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-1.16.8.tgz", + "integrity": "sha512-2hUSmfXPGaIDOT5LJSOl62JwZ+9cQ24nDhNNc64gaMm+RpriDgq+tIDYXrWqXtaFjYT41b4K/RhaEiuSxYtBNQ==", + "dev": true, + "dependencies": { + "buffer-browserify": "~0.0.1", + "coffee-script": "1.x.x", + "commondir": "~0.0.1", + "crypto-browserify": "~0", + "deputy": "~0.0.3", + "detective": "~0.2.0", + "http-browserify": "~0.1.1", + "nub": "~0.0.0", + "optimist": "~0.3.4", + "resolve": "~0.2.0", + "syntax-error": "~0.0.0", + "vm-browserify": "~0.0.0" + }, + "bin": { + "browserify": "bin/cmd.js" + } + }, + "node_modules/browserify-server": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/browserify-server/-/browserify-server-2.0.4.tgz", + "integrity": "sha512-aGN6yQwoVcOVu3eakjDALcGtEnRD1boQYmLCFJsaCYOm1MqYCPU5jQ0FcROw8I93krTyxJ5jtdUTQzq0Xd40Aw==", + "dev": true, + "dependencies": { + "browserify": "~1.16.1", + "ecstatic": "~0.1.6", + "filed": "0.0.7", + "optimist": "~0.3.4" + }, + "bin": { + "browserify-server": "bin/browserify-server.js" + } + }, + "node_modules/buffer-browserify": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/buffer-browserify/-/buffer-browserify-0.0.5.tgz", + "integrity": "sha1-iqaGMciogpxqTufvmjrH8sMemD4=", + "deprecated": "Package not maintained. Recent browserify uses https://github.com/feross/buffer", + "dev": true, + "dependencies": { + "base64-js": "0.0.2" + } + }, + "node_modules/camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true + }, + "node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", + "dev": true, + "dependencies": { + "exit": "0.1.2", + "glob": "^7.1.1" + }, + "engines": { + "node": ">=0.2.5" + } + }, + "node_modules/cli/node_modules/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "node_modules/coa": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", + "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", + "dev": true, + "dependencies": { + "q": "^1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", + "deprecated": "CoffeeScript on NPM has moved to \"coffeescript\" (no hyphen)", + "dev": true, + "bin": { + "cake": "bin/cake", + "coffee": "bin/coffee" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "dependencies": { + "graceful-readlink": ">= 1.0.0" + }, + "engines": { + "node": ">= 0.6.x" + } + }, + "node_modules/commondir": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-0.0.2.tgz", + "integrity": "sha1-xJyIgMb+loRLs1Jd0ucxQFDDie4=", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/concat-stream": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.0.tgz", + "integrity": "sha512-litEocitzYgqQ0IPaoLw+tCHcVcJJYW05+SAhH+LS9qutSC7iuejvawts3cUYQycZbRbLsjG8mCJLQi2KX5kEw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "inherits": "~2.0.1", + "readable-stream": "~2.0.0", + "typedarray": "~0.0.5" + } + }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "dependencies": { + "date-now": "^0.1.4" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "node_modules/cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha512-FFN5KwpvvQTTS5hWPxrU8/QE4kQUc6uwZcrnlMBN82t1MgAtq8mnoDwINBly9Tdr02seeIIhtdF+UH1feBYGog==", + "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", + "dev": true, + "dependencies": { + "boom": "2.x.x" + }, + "engines": { + "node": ">=0.10.40" + } + }, + "node_modules/crypto-browserify": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-0.4.0.tgz", + "integrity": "sha1-JG9qM3uITJn/6L+whaGEruYMM/M=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/css-selector-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-1.2.0.tgz", + "integrity": "sha1-gtqv9PacSndnIbO2vu3X8fUJzJQ=", + "dev": true, + "engines": [ + "node >= 0.4.0" + ] + }, + "node_modules/cssmin": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/cssmin/-/cssmin-0.4.3.tgz", + "integrity": "sha1-yRlAd+Dr2s1pHV9ZAVudgZ840BU=", + "dev": true, + "bin": { + "cssmin": "bin/cssmin" + } + }, + "node_modules/cssom": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.1.tgz", + "integrity": "sha1-yeN+8kkOZPbRuqEP2oUiVwgsJdM=", + "dev": true + }, + "node_modules/cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dashdash": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz", + "integrity": "sha1-KeSGxUGL8PNWA0qZPVFoajPoQUE=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dashdash/node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "node_modules/debug": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "integrity": "sha512-EohAb3+DSHSGx8carOSKJe8G0ayV5/i609OD0J2orCkuyae7SyZSz2aoLmQF2s0Pj5gITDebwPH7GFBlqOUQ1Q==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/deputy": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/deputy/-/deputy-0.0.4.tgz", + "integrity": "sha1-7cAKnvXFNSfEBTKFNMmXla2kHL8=", + "dev": true, + "dependencies": { + "detective": "~0.2.0", + "mkdirp": "~0.3.3" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/deputy/node_modules/mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true + }, + "node_modules/detective": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-0.2.1.tgz", + "integrity": "sha1-nOkmAf0iOBDClDKtA0+MYti4ZU8=", + "dev": true, + "dependencies": { + "esprima": "~0.9.9" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/detective/node_modules/esprima": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-0.9.9.tgz", + "integrity": "sha1-G5CSXJddYy1ygpOcO7nDpCPDBJA=", + "dev": true, + "bin": { + "esparse": "bin/esparse.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "dependencies": { + "domelementtype": "~1.1.1", + "entities": "~1.1.1" + } + }, + "node_modules/dom-serializer/node_modules/domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + }, + "node_modules/domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "deprecated": "update to domelementtype@1.3.1", + "dev": true + }, + "node_modules/domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "dev": true, + "dependencies": { + "domelementtype": "1" + } + }, + "node_modules/domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0" + } + }, + "node_modules/ecstatic": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-0.1.7.tgz", + "integrity": "sha512-3CLNsqzx01cZ6rbksPg5s3lCKII0edmfiutKf+2xcQgWP/FtPNvI9hkil9eYqO2pDPFVdaSUnNagz+bMZhQd0w==", + "deprecated": "This package is unmaintained and deprecated. See the GH Issue 259.", + "dev": true, + "dependencies": { + "ent": "0.0.x", + "mime": "1.2.5" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ent": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ent/-/ent-0.0.7.tgz", + "integrity": "sha1-g11Of556jUkhxpLpAQ7JdtpemUk=", + "dev": true + }, + "node_modules/entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esprima": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.1.tgz", + "integrity": "sha1-AtvMWsPs6BBwN3+ZFY7HQqtd2gY=", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/exec-sh": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz", + "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==", + "dev": true, + "dependencies": { + "merge": "^1.2.0" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extract-zip": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.5.0.tgz", + "integrity": "sha512-Ht7oUiEXWnX5BvLzMX/UBNIjrAs53lhXtNxMNeUe8Nv0S8rfy5UGqsKOXpP8ZQMWLvheOvRqYYShBoj6fTO9bg==", + "dev": true, + "dependencies": { + "concat-stream": "1.5.0", + "debug": "0.7.4", + "mkdirp": "0.5.0", + "yauzl": "2.4.1" + }, + "bin": { + "extract-zip": "cli.js" + } + }, + "node_modules/extract-zip/node_modules/mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha512-xjjNGy+ry1lhtIKcr2PT6ok3aszhQfgrUDp4OZLHacgRgFmF6XR9XCOJVcXlVGQonIqXcK1DvqgKKQOPWYGSfw==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", + "dev": true, + "engines": { + "node": "> 0.1.90" + } + }, + "node_modules/faye-websocket": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.4.4.tgz", + "integrity": "sha1-wUxbO/FNdBf/v9mQwKdJXNnzN7w=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/filed": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/filed/-/filed-0.0.7.tgz", + "integrity": "sha1-MIfsUx+5p4YApuyOCxBuLFdNl3M=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.1.tgz", + "integrity": "sha1-rjFduaSQf6BlUCMEpm13M0de43w=", + "dev": true, + "dependencies": { + "async": "^2.0.1", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.11" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/form-data/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/form-data/node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "node_modules/generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "dependencies": { + "is-property": "^1.0.0" + } + }, + "node_modules/getpass": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", + "integrity": "sha1-KD/9n8ElaECHUxHBtg6MQBhxEOY=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/getpass/node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/graceful-fs": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.10.tgz", + "integrity": "sha1-8tcgwiCS90Mih3XHXjYSYyUB8TE=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "node_modules/h": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/h/-/h-0.1.0.tgz", + "integrity": "sha1-JCEf4dnO8rNsro/4JVYG6hLs37U=", + "dev": true + }, + "node_modules/har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "deprecated": "this library is no longer supported", + "dev": true, + "dependencies": { + "chalk": "^1.1.1", + "commander": "^2.9.0", + "is-my-json-valid": "^2.12.4", + "pinkie-promise": "^2.0.0" + }, + "bin": { + "har-validator": "bin/har-validator" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hasha": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", + "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", + "dev": true, + "dependencies": { + "is-stream": "^1.0.1", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha512-X8xbmTc1cbPXcQV4WkLcRMALuyoxhfpFATmyuCxJPOAvrDS4DNnsTAOmKUxMTOWU6TzrTOkxPKwIx5ZOpJVSrg==", + "deprecated": "This module moved to @hapi/hawk. Please make sure to switch over as this distribution is no longer supported and may contain bugs and critical security issues.", + "dev": true, + "dependencies": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + }, + "engines": { + "node": ">=0.10.32" + } + }, + "node_modules/hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha512-V6Yw1rIcYV/4JsnggjBU0l4Kr+EXhpwqXRusENU1Xx6ro00IHPHYNynCuBTOZAPlr3AAmLvchH9I7N/VUdvOwQ==", + "deprecated": "This version has been deprecated in accordance with the hapi support policy (hapi.im/support). Please upgrade to the latest version to get the best features, bug fixes, and security patches. If you are unable to upgrade at this time, paid support is available for older versions (hapi.im/commercial).", + "dev": true, + "engines": { + "node": ">=0.10.40" + } + }, + "node_modules/hound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/hound/-/hound-1.0.4.tgz", + "integrity": "sha1-GP6aYrbO9mlJ2AJQjonKAKVcDIc=", + "dev": true, + "engines": { + "node": ">=0.7.1" + } + }, + "node_modules/htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "dev": true, + "dependencies": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + } + }, + "node_modules/http-browserify": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-0.1.14.tgz", + "integrity": "sha1-nIs/lAAiBFR8fL5Saa/i6mL3HH8=", + "dev": true, + "dependencies": { + "Base64": "~0.1.2", + "concat-stream": "~1.0.0" + } + }, + "node_modules/http-browserify/node_modules/concat-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.0.1.tgz", + "integrity": "sha1-AYsYvBx9BzotyCqkhEI0GixN158=", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "dependencies": { + "bops": "0.0.6" + } + }, + "node_modules/http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "dependencies": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/immutable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", + "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", + "dev": true + }, + "node_modules/indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-my-ip-valid": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.1.tgz", + "integrity": "sha512-jxc8cBcOWbNK2i2aTkCZP6i7wkHF1bqKFrwEHuN5Jtg5BSaZHUZQ/JTOJwoV41YvHnOaRyWWh72T/KvfNz9DJg==", + "dev": true + }, + "node_modules/is-my-json-valid": { + "version": "2.20.6", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.6.tgz", + "integrity": "sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw==", + "dev": true, + "dependencies": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^5.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/isexe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz", + "integrity": "sha1-NvPiLmB1CSD15yQaR2qMakInWtA=", + "dev": true + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js-yaml/node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/jsbn": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz", + "integrity": "sha1-ZQmH2g3XT06/WhE3eiqi0nPpff0=", + "dev": true + }, + "node_modules/jshint": { + "version": "2.13.5", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.5.tgz", + "integrity": "sha512-dB2n1w3OaQ35PLcBGIWXlszjbPZwsgZoxsg6G8PtNf2cFMC1l0fObkYLUuXqTTdi6tKw4sAjfUseTdmDMHQRcg==", + "dev": true, + "dependencies": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.21", + "minimatch": "~3.0.2", + "strip-json-comments": "1.0.x" + }, + "bin": { + "jshint": "bin/jshint" + } + }, + "node_modules/jshint/node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/jsprim/node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/kew": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", + "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", + "dev": true + }, + "node_modules/klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/live-reload": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/live-reload/-/live-reload-1.1.1.tgz", + "integrity": "sha512-YjouhWA89l9nWBO9ZpKJGxoZJ8bkAz1KBOKaefBO7FzvVGJKZX+WN2xdBroRy3SKbluhStQ3HOIZNozmoDEDLQ==", + "dev": true, + "dependencies": { + "browserify-server": "~2.0.3", + "filed": "0.0.7", + "hound": "~1.0.4", + "optimist": "~0.3.4", + "reconnect": "~0.1.3", + "shoe": "0.0.15", + "watchr": "~2.1.5" + }, + "bin": { + "live-reload": "bin/reload.js" + } + }, + "node_modules/lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ==", + "dev": true + }, + "node_modules/merge": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", + "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", + "dev": true + }, + "node_modules/mime": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.5.tgz", + "integrity": "sha512-QfwTOA+zRHSZXxl9Y7ue5ifKDhU1prnh0dO67Vgcl7Lcx0+79vL9A1ln0qtVur8CFSdYq5Zhnw9DDZQgwDh8Ng==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/mime-db": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.25.0.tgz", + "integrity": "sha1-wY29fHOl2/b0SgJNwNFloeexw5I=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.13.tgz", + "integrity": "sha1-4HqqnGxrmnyjASxpADrSWjnpKog=", + "dev": true, + "dependencies": { + "mime-db": "~1.25.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", + "dev": true, + "dependencies": { + "brace-expansion": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==", + "dev": true + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp/node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/mustache": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.2.1.tgz", + "integrity": "sha1-LEDKIcJ49TFQaCvPkJDkGjM5uHY=", + "dev": true, + "bin": { + "mustache": "bin/mustache" + }, + "engines": { + "npm": ">=1.4.0" + } + }, + "node_modules/node-uuid": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz", + "integrity": "sha1-baWhdmjEs91ZYjvaEc9/pMH2Cm8=", + "deprecated": "Use uuid module instead", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nub": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/nub/-/nub-0.0.0.tgz", + "integrity": "sha1-s2m9Mr3eZq9ZYFw7BSC8IZ3MwE8=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "dev": true, + "dependencies": { + "wordwrap": "~0.0.2" + } + }, + "node_modules/os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "dependencies": { + "lcid": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parallelshell": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parallelshell/-/parallelshell-2.0.0.tgz", + "integrity": "sha512-EJJKjVi68lT+1CnuejYfoJdTxoChOIwDjy21bXFrH3YoJjcDR/8MsotXOY6U2p3rDi2BqYNVySAlF0e9B4S6fA==", + "dev": true, + "bin": { + "parallelshell": "index.js" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "node_modules/phantomjs": { + "version": "1.9.20", + "resolved": "https://registry.npmjs.org/phantomjs/-/phantomjs-1.9.20.tgz", + "integrity": "sha1-RCSsog4U0lXAsIia9va4lz2hDg0=", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "extract-zip": "~1.5.0", + "fs-extra": "~0.26.4", + "hasha": "^2.2.0", + "kew": "~0.7.0", + "progress": "~1.1.8", + "request": "~2.67.0", + "request-progress": "~2.0.1", + "which": "~1.2.2" + }, + "bin": { + "phantomjs": "bin/phantomjs" + } + }, + "node_modules/phantomjs/node_modules/fs-extra": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", + "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkginfo": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", + "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/prettysize": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/prettysize/-/prettysize-0.0.3.tgz", + "integrity": "sha1-FK//amReWRpN3xxykZwjtBRhgaE=", + "dev": true + }, + "node_modules/process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "node_modules/progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true, + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qs": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.1.tgz", + "integrity": "sha512-sh/hmLUTLEiYFhSbRvkM4zj6fMWnbqQt9wrppR2LJA/U/u4xS2eWN8LBE1xc79ExYZJBVZYSMBv/INC7wpE+fw==", + "dev": true, + "engines": ">=0.10.40" + }, + "node_modules/readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reconnect": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/reconnect/-/reconnect-0.1.5.tgz", + "integrity": "sha1-3/6iUtYb6/swLsFwzvc9LS52WPI=", + "dev": true, + "dependencies": { + "backoff": "~1.0.0", + "h": "~0.1.0", + "shoe": "~0.0.7" + } + }, + "node_modules/request": { + "version": "2.67.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.67.0.tgz", + "integrity": "sha512-fzMRDWVEdMktE3foqvL4CBmC+AR8WvcP8pIPx6JSqqhWuPr+BxX9tKx4XiijfyeKtqqRMNpHDWqFMw4JlRPIJg==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, + "dependencies": { + "aws-sign2": "~0.6.0", + "bl": "~1.0.0", + "caseless": "~0.11.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~1.0.0-rc3", + "har-validator": "~2.0.2", + "hawk": "~3.1.0", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "node-uuid": "~1.4.7", + "oauth-sign": "~0.8.0", + "qs": "~5.2.0", + "stringstream": "~0.0.4", + "tough-cookie": "~2.2.0", + "tunnel-agent": "~0.4.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/request-progress": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", + "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", + "dev": true, + "dependencies": { + "throttleit": "^1.0.0" + } + }, + "node_modules/resolve": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.2.8.tgz", + "integrity": "sha1-/bF9SrsOyvb4DWesA88pAIj2wNA=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/rimraf": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", + "dev": true, + "dependencies": { + "glob": "^7.0.5" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sass": { + "version": "1.54.4", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.4.tgz", + "integrity": "sha512-3tmF16yvnBwtlPrNBHw/H907j8MlOX8aTBnlNX1yrKx24RKcJGPyLhFUwkoKBKesR3unP93/2z14Ll8NicwQUA==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/sax": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.6.tgz", + "integrity": "sha1-XWFr6KXmB9VOEUr65Vt+ry/MMkA=", + "dev": true + }, + "node_modules/shoe": { + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/shoe/-/shoe-0.0.15.tgz", + "integrity": "sha512-XM5aTvK9kzdYYYZ0sr4pqteQ1jeHucXgSa6ueQE7CrDZTa+1bXGbQWT5EPyIw4LYhZ0fur43cGZgnifJJPfSOQ==", + "bundleDependencies": [ + "sockjs-client" + ], + "dev": true, + "dependencies": { + "sockjs": "0.3.7" + } + }, + "node_modules/shoe/node_modules/sockjs-client": { + "version": "0.0.0-unreleasable", + "extraneous": true, + "inBundle": true + }, + "node_modules/sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha512-7bgVOAnPj3XjrKY577S+puCKGCRlUrcrEdsMeRXlg9Ghf5df/xNi6sONUa43WrHUd3TjJBF7O04jYoiY0FVa0A==", + "deprecated": "This module moved to @hapi/sntp. Please make sure to switch over as this distribution is no longer supported and may contain bugs and critical security issues.", + "dev": true, + "dependencies": { + "hoek": "2.x.x" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/sockjs": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.7.tgz", + "integrity": "sha512-Hhb9Z0yY5QWc4rSXcGgByUhijT/adjyL6SpoLeZgXbpa8rd2s9Dbr1voP/8eeLDYET4AHTffPxz4kgJQH8WwrA==", + "dev": true, + "dependencies": { + "faye-websocket": "0.4.4", + "node-uuid": "1.3.3" + } + }, + "node_modules/sockjs/node_modules/node-uuid": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.3.3.tgz", + "integrity": "sha512-xKQtL5imfvX6PvUmgJyU/XaNT/l8tKvs+sJ6KLOmIzk/H8+sm7uE80QlPmmu3l1uirvRL3kZqtJPWoQBWT9gQw==", + "deprecated": "Use uuid module instead", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sshpk/node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "dev": true + }, + "node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true, + "bin": { + "strip-json-comments": "cli.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/svg-sprite": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/svg-sprite/-/svg-sprite-1.0.20.tgz", + "integrity": "sha512-6tyuv5GgaG/HkXYCi+DTa2iErgt6KsJgqgpYlGjuz8uNlhGKxAP6PtkNlsea2Zqqmum5Ov1BubQR0kkdA5uUKA==", + "dev": true, + "dependencies": { + "async": "^0.9.0", + "css-selector-parser": "^1.0.4", + "cssmin": "^0.4.3", + "cssom": "^0.3.0", + "glob": "^5.0.1", + "js-yaml": "^3.2.7", + "lodash": "^3.4.0", + "mkdirp": "^0.5.0", + "mustache": "^2.0.0", + "phantomjs": "^1.9.16", + "prettysize": "^0.0.3", + "svgo": "^0.5.0", + "vinyl": "^0.4.6", + "winston": "^0.9.0", + "xmldom": "^0.1.19", + "xpath": "^0.0.9", + "yargs": "^3.4.5" + }, + "bin": { + "svg-sprite": "bin/svg-sprite.js" + } + }, + "node_modules/svgo": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.5.6.tgz", + "integrity": "sha512-KSiqo2B+gE0Vk7iItrsOmvKOu5o9eZ0fI6oJ3JhemXqIWRVL9KoSIfLIi2xy4gl8nU2kJRjM4n1RnvPmv9ncFA==", + "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.", + "dev": true, + "dependencies": { + "coa": "~1.0.1", + "colors": "~1.1.2", + "js-yaml": "~3.3.1", + "mkdirp": "~0.5.1", + "sax": "~1.1.1", + "whet.extend": "~0.9.9" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/svgo/node_modules/esprima": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.2.0.tgz", + "integrity": "sha1-QpLB1o5Bc9gV+iKQ3Hr8ltgfzYM=", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/svgo/node_modules/js-yaml": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.3.1.tgz", + "integrity": "sha512-fjgnhG5HijmXtlBCMcU0JyCq/VA8YtdBwFNIBDiu3hpJ5Zsvs7993VC0XNNSiKoM8g399vY+21yqzT/TRS3KMQ==", + "dev": true, + "dependencies": { + "argparse": "~1.0.2", + "esprima": "~2.2.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/syntax-error": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-0.0.1.tgz", + "integrity": "sha512-Pg2FzUaDR1Zlkl5ol+6LGAES7PjqcvfUpa2OKZZhww4VrRyjZyU2v+4C0dcYfhwNl2FMaZW9mXHzX0kS9x3xXw==", + "dev": true, + "dependencies": { + "esprima": "~0.9.9" + } + }, + "node_modules/syntax-error/node_modules/esprima": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-0.9.9.tgz", + "integrity": "sha1-G5CSXJddYy1ygpOcO7nDpCPDBJA=", + "dev": true, + "bin": { + "esparse": "bin/esparse.js" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/to-utf8": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/to-utf8/-/to-utf8-0.0.1.tgz", + "integrity": "sha1-0Xrqcv8vujm55DYBvns/9y4ImFI=", + "dev": true + }, + "node_modules/tough-cookie": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz", + "integrity": "sha512-Knz9Yr0hlBoWQgUKzOIvRg5adinizAf49i2gHRhj6cLjlM304zRw7uyiY22ADniDxnPHXfIeyQD0EAkgpIz0ow==", + "deprecated": "ReDoS vulnerability parsing Set-Cookie https://nodesecurity.io/advisories/130", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha512-e0IoVDWx8SDHc/hwFTqJDQ7CCDTEeGhmcT9jkWJjoGQSpgBz20nAMr80E3Tpk7PatJ1b37DQDgJR3CNSzcMOZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.3.tgz", + "integrity": "sha1-PaOC9nDyXe1417PReSEZvKC3Ey0=", + "dev": true + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "dependencies": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + }, + "engines": { + "node": ">= 0.9" + } + }, + "node_modules/vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "dependencies": { + "indexof": "0.0.1" + } + }, + "node_modules/watch": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/watch/-/watch-0.19.3.tgz", + "integrity": "sha512-foeUUwledbAQMY93TffBBnftHifGqRzB9QbJC5FjuRuTyUQJLDfZUedxlarZr/oGvCQM3LpVXg7HGEe8syPVow==", + "deprecated": "Install watch@1.0.0 instead", + "dev": true, + "dependencies": { + "exec-sh": "^0.2.0", + "minimist": "^1.2.0" + }, + "bin": { + "watch": "cli.js" + }, + "engines": { + "node": ">=0.1.95" + } + }, + "node_modules/watch/node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/watchr": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/watchr/-/watchr-2.1.6.tgz", + "integrity": "sha1-bciVv2yVq29eBtgRlIsyCphBOJE=", + "dev": true, + "dependencies": { + "bal-util": "1.13.x" + }, + "bin": { + "watchr": "bin/watchr" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/whet.extend": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", + "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", + "dev": true, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/which": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.12.tgz", + "integrity": "sha1-3me15FAmnxlJCe8j7OTr5Bb6EZI=", + "dev": true, + "dependencies": { + "isexe": "^1.1.1" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", + "dev": true, + "bin": { + "window-size": "cli.js" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/winston": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-0.9.0.tgz", + "integrity": "sha1-tXJubEIpHjBeNihs566fO3SlJ6g=", + "dev": true, + "dependencies": { + "async": "0.9.x", + "colors": "1.0.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "isstream": "0.1.x", + "pkginfo": "0.3.x", + "stack-trace": "0.0.x" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/winston/node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xmldom": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", + "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==", + "deprecated": "Deprecated due to CVE-2021-21366 resolved in 0.5.0", + "dev": true, + "engines": { + "node": ">=0.1" + } + }, + "node_modules/xpath": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.9.tgz", + "integrity": "sha1-s57qHq+9yOzdohrUkcjbQPAT+1Q=", + "dev": true, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true + }, + "node_modules/yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "dev": true, + "dependencies": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" + } + }, + "node_modules/yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "dependencies": { + "fd-slicer": "~1.0.1" + } + } + }, + "dependencies": { + "ansi-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.0.0.tgz", + "integrity": "sha1-xQYbbg74qBd15Q9dZhUb9r83EQc=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true + }, + "backoff": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/backoff/-/backoff-1.0.0.tgz", + "integrity": "sha1-AJgveBWOxtA/mWk+wPtfeyrR4o4=", + "dev": true + }, + "bal-util": { + "version": "1.13.13", + "resolved": "https://registry.npmjs.org/bal-util/-/bal-util-1.13.13.tgz", + "integrity": "sha1-YyxJUgo2fsWqhUaI4Qgn2bUZMl8=", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "Base64": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/Base64/-/Base64-0.1.4.tgz", + "integrity": "sha1-6fbGvvVn/WNepBYqsU3TKedKpt4=", + "dev": true + }, + "base64-js": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.2.tgz", + "integrity": "sha1-Ak8Pcq+iW3X5wO5zzU9V7Bvtl4Q=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.0.tgz", + "integrity": "sha1-PKdrhSQccXC/fZcD57mqdGMAQNQ=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, + "bl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.0.3.tgz", + "integrity": "sha512-phbvN+yOk05EGoFcV/0S8N8ShnJqf6VCWRAw5he2gvRwBubFt/OzmcTNGqBt5b7Y4RK3YCgf6jrgGSR0Cwtsgw==", + "dev": true, + "requires": { + "readable-stream": "~2.0.5" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + } + } + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha512-KbiZEa9/vofNcVJXGwdWWn25reQ3V3dHBWbS07FTF3/TOehLnm9GEhJV4T6ZvGPkShRpmUqYwnaCrkj0mRnP6Q==", + "dev": true, + "requires": { + "hoek": "2.x.x" + } + }, + "bops": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/bops/-/bops-0.0.6.tgz", + "integrity": "sha1-CC0dVfoB5g29wuvC26N/ZZVUzzo=", + "dev": true, + "requires": { + "base64-js": "0.0.2", + "to-utf8": "0.0.1" + } + }, + "bower": { + "version": "1.8.14", + "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.14.tgz", + "integrity": "sha512-8Rq058FD91q9Nwthyhw0la9fzpBz0iwZTrt51LWl+w+PnJgZk9J+5wp3nibsJcIUPglMYXr4NRBaR+TUj0OkBQ==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserify": { + "version": "1.16.8", + "resolved": "https://registry.npmjs.org/browserify/-/browserify-1.16.8.tgz", + "integrity": "sha512-2hUSmfXPGaIDOT5LJSOl62JwZ+9cQ24nDhNNc64gaMm+RpriDgq+tIDYXrWqXtaFjYT41b4K/RhaEiuSxYtBNQ==", + "dev": true, + "requires": { + "buffer-browserify": "~0.0.1", + "coffee-script": "1.x.x", + "commondir": "~0.0.1", + "crypto-browserify": "~0", + "deputy": "~0.0.3", + "detective": "~0.2.0", + "http-browserify": "~0.1.1", + "nub": "~0.0.0", + "optimist": "~0.3.4", + "resolve": "~0.2.0", + "syntax-error": "~0.0.0", + "vm-browserify": "~0.0.0" + } + }, + "browserify-server": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/browserify-server/-/browserify-server-2.0.4.tgz", + "integrity": "sha512-aGN6yQwoVcOVu3eakjDALcGtEnRD1boQYmLCFJsaCYOm1MqYCPU5jQ0FcROw8I93krTyxJ5jtdUTQzq0Xd40Aw==", + "dev": true, + "requires": { + "browserify": "~1.16.1", + "ecstatic": "~0.1.6", + "filed": "0.0.7", + "optimist": "~0.3.4" + } + }, + "buffer-browserify": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/buffer-browserify/-/buffer-browserify-0.0.5.tgz", + "integrity": "sha1-iqaGMciogpxqTufvmjrH8sMemD4=", + "dev": true, + "requires": { + "base64-js": "0.0.2" + } + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + }, + "caseless": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", + "integrity": "sha1-cVuW6phBWTzDMGeSP17GDr2k99c=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cli/-/cli-1.0.1.tgz", + "integrity": "sha1-IoF1NPJL+klQw01TLUjsvGIbjBQ=", + "dev": true, + "requires": { + "exit": "0.1.2", + "glob": "^7.1.1" + }, + "dependencies": { + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "coa": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", + "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", + "dev": true, + "requires": { + "q": "^1.1.2" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "commondir": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-0.0.2.tgz", + "integrity": "sha1-xJyIgMb+loRLs1Jd0ucxQFDDie4=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.0.tgz", + "integrity": "sha512-litEocitzYgqQ0IPaoLw+tCHcVcJJYW05+SAhH+LS9qutSC7iuejvawts3cUYQycZbRbLsjG8mCJLQi2KX5kEw==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~2.0.0", + "typedarray": "~0.0.5" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + } + } + }, + "console-browserify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", + "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", + "dev": true, + "requires": { + "date-now": "^0.1.4" + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha512-FFN5KwpvvQTTS5hWPxrU8/QE4kQUc6uwZcrnlMBN82t1MgAtq8mnoDwINBly9Tdr02seeIIhtdF+UH1feBYGog==", + "dev": true, + "requires": { + "boom": "2.x.x" + } + }, + "crypto-browserify": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-0.4.0.tgz", + "integrity": "sha1-JG9qM3uITJn/6L+whaGEruYMM/M=", + "dev": true + }, + "css-selector-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-1.2.0.tgz", + "integrity": "sha1-gtqv9PacSndnIbO2vu3X8fUJzJQ=", + "dev": true + }, + "cssmin": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/cssmin/-/cssmin-0.4.3.tgz", + "integrity": "sha1-yRlAd+Dr2s1pHV9ZAVudgZ840BU=", + "dev": true + }, + "cssom": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.1.tgz", + "integrity": "sha1-yeN+8kkOZPbRuqEP2oUiVwgsJdM=", + "dev": true + }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=", + "dev": true + }, + "dashdash": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz", + "integrity": "sha1-KeSGxUGL8PNWA0qZPVFoajPoQUE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "date-now": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", + "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", + "dev": true + }, + "debug": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "integrity": "sha512-EohAb3+DSHSGx8carOSKJe8G0ayV5/i609OD0J2orCkuyae7SyZSz2aoLmQF2s0Pj5gITDebwPH7GFBlqOUQ1Q==", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "deputy": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/deputy/-/deputy-0.0.4.tgz", + "integrity": "sha1-7cAKnvXFNSfEBTKFNMmXla2kHL8=", + "dev": true, + "requires": { + "detective": "~0.2.0", + "mkdirp": "~0.3.3" + }, + "dependencies": { + "mkdirp": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz", + "integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc=", + "dev": true + } + } + }, + "detective": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-0.2.1.tgz", + "integrity": "sha1-nOkmAf0iOBDClDKtA0+MYti4ZU8=", + "dev": true, + "requires": { + "esprima": "~0.9.9" + }, + "dependencies": { + "esprima": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-0.9.9.tgz", + "integrity": "sha1-G5CSXJddYy1ygpOcO7nDpCPDBJA=", + "dev": true + } + } + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "requires": { + "domelementtype": "~1.1.1", + "entities": "~1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true + }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true + }, + "domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "requires": { + "jsbn": "~0.1.0" + } + }, + "ecstatic": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-0.1.7.tgz", + "integrity": "sha512-3CLNsqzx01cZ6rbksPg5s3lCKII0edmfiutKf+2xcQgWP/FtPNvI9hkil9eYqO2pDPFVdaSUnNagz+bMZhQd0w==", + "dev": true, + "requires": { + "ent": "0.0.x", + "mime": "1.2.5" + } + }, + "ent": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ent/-/ent-0.0.7.tgz", + "integrity": "sha1-g11Of556jUkhxpLpAQ7JdtpemUk=", + "dev": true + }, + "entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esprima": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.1.tgz", + "integrity": "sha1-AtvMWsPs6BBwN3+ZFY7HQqtd2gY=", + "dev": true + }, + "exec-sh": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.2.tgz", + "integrity": "sha512-FIUCJz1RbuS0FKTdaAafAByGS0CPvU3R0MeHxgtl+djzCc//F8HakL8GzmVNZanasTbTAY/3DRFA0KpVqj/eAw==", + "dev": true, + "requires": { + "merge": "^1.2.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extract-zip": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.5.0.tgz", + "integrity": "sha512-Ht7oUiEXWnX5BvLzMX/UBNIjrAs53lhXtNxMNeUe8Nv0S8rfy5UGqsKOXpP8ZQMWLvheOvRqYYShBoj6fTO9bg==", + "dev": true, + "requires": { + "concat-stream": "1.5.0", + "debug": "0.7.4", + "mkdirp": "0.5.0", + "yauzl": "2.4.1" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha512-xjjNGy+ry1lhtIKcr2PT6ok3aszhQfgrUDp4OZLHacgRgFmF6XR9XCOJVcXlVGQonIqXcK1DvqgKKQOPWYGSfw==", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", + "dev": true + }, + "faye-websocket": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.4.4.tgz", + "integrity": "sha1-wUxbO/FNdBf/v9mQwKdJXNnzN7w=", + "dev": true + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "dev": true, + "requires": { + "pend": "~1.2.0" + } + }, + "filed": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/filed/-/filed-0.0.7.tgz", + "integrity": "sha1-MIfsUx+5p4YApuyOCxBuLFdNl3M=", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-1.0.1.tgz", + "integrity": "sha1-rjFduaSQf6BlUCMEpm13M0de43w=", + "dev": true, + "requires": { + "async": "^2.0.1", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.11" + }, + "dependencies": { + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "^1.0.0" + } + }, + "getpass": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz", + "integrity": "sha1-KD/9n8ElaECHUxHBtg6MQBhxEOY=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "graceful-fs": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.10.tgz", + "integrity": "sha1-8tcgwiCS90Mih3XHXjYSYyUB8TE=", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "h": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/h/-/h-0.1.0.tgz", + "integrity": "sha1-JCEf4dnO8rNsro/4JVYG6hLs37U=", + "dev": true + }, + "har-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", + "integrity": "sha1-zcvAgYgmWtEZtqWnyKtw7s+10n0=", + "dev": true, + "requires": { + "chalk": "^1.1.1", + "commander": "^2.9.0", + "is-my-json-valid": "^2.12.4", + "pinkie-promise": "^2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "hasha": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", + "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", + "dev": true, + "requires": { + "is-stream": "^1.0.1", + "pinkie-promise": "^2.0.0" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha512-X8xbmTc1cbPXcQV4WkLcRMALuyoxhfpFATmyuCxJPOAvrDS4DNnsTAOmKUxMTOWU6TzrTOkxPKwIx5ZOpJVSrg==", + "dev": true, + "requires": { + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha512-V6Yw1rIcYV/4JsnggjBU0l4Kr+EXhpwqXRusENU1Xx6ro00IHPHYNynCuBTOZAPlr3AAmLvchH9I7N/VUdvOwQ==", + "dev": true + }, + "hound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/hound/-/hound-1.0.4.tgz", + "integrity": "sha1-GP6aYrbO9mlJ2AJQjonKAKVcDIc=", + "dev": true + }, + "htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "dev": true, + "requires": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + } + }, + "http-browserify": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/http-browserify/-/http-browserify-0.1.14.tgz", + "integrity": "sha1-nIs/lAAiBFR8fL5Saa/i6mL3HH8=", + "dev": true, + "requires": { + "Base64": "~0.1.2", + "concat-stream": "~1.0.0" + }, + "dependencies": { + "concat-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.0.1.tgz", + "integrity": "sha1-AYsYvBx9BzotyCqkhEI0GixN158=", + "dev": true, + "requires": { + "bops": "0.0.6" + } + } + } + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "requires": { + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "immutable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", + "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==", + "dev": true + }, + "indexof": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", + "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-my-ip-valid": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.1.tgz", + "integrity": "sha512-jxc8cBcOWbNK2i2aTkCZP6i7wkHF1bqKFrwEHuN5Jtg5BSaZHUZQ/JTOJwoV41YvHnOaRyWWh72T/KvfNz9DJg==", + "dev": true + }, + "is-my-json-valid": { + "version": "2.20.6", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.6.tgz", + "integrity": "sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw==", + "dev": true, + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^5.0.0", + "xtend": "^4.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz", + "integrity": "sha1-NvPiLmB1CSD15yQaR2qMakInWtA=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + } + } + }, + "jsbn": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz", + "integrity": "sha1-ZQmH2g3XT06/WhE3eiqi0nPpff0=", + "dev": true + }, + "jshint": { + "version": "2.13.5", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.13.5.tgz", + "integrity": "sha512-dB2n1w3OaQ35PLcBGIWXlszjbPZwsgZoxsg6G8PtNf2cFMC1l0fObkYLUuXqTTdi6tKw4sAjfUseTdmDMHQRcg==", + "dev": true, + "requires": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.21", + "minimatch": "~3.0.2", + "strip-json-comments": "1.0.x" + }, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + } + } + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true + }, + "jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true + } + } + }, + "kew": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", + "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", + "dev": true + }, + "klaw": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", + "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.9" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "live-reload": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/live-reload/-/live-reload-1.1.1.tgz", + "integrity": "sha512-YjouhWA89l9nWBO9ZpKJGxoZJ8bkAz1KBOKaefBO7FzvVGJKZX+WN2xdBroRy3SKbluhStQ3HOIZNozmoDEDLQ==", + "dev": true, + "requires": { + "browserify-server": "~2.0.3", + "filed": "0.0.7", + "hound": "~1.0.4", + "optimist": "~0.3.4", + "reconnect": "~0.1.3", + "shoe": "0.0.15", + "watchr": "~2.1.5" + } + }, + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ==", + "dev": true + }, + "merge": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", + "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", + "dev": true + }, + "mime": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.5.tgz", + "integrity": "sha512-QfwTOA+zRHSZXxl9Y7ue5ifKDhU1prnh0dO67Vgcl7Lcx0+79vL9A1ln0qtVur8CFSdYq5Zhnw9DDZQgwDh8Ng==", + "dev": true + }, + "mime-db": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.25.0.tgz", + "integrity": "sha1-wY29fHOl2/b0SgJNwNFloeexw5I=", + "dev": true + }, + "mime-types": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.13.tgz", + "integrity": "sha1-4HqqnGxrmnyjASxpADrSWjnpKog=", + "dev": true, + "requires": { + "mime-db": "~1.25.0" + } + }, + "minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha1-Kk5AkLlrLbBqnX3wEFWmKnfJt3Q=", + "dev": true, + "requires": { + "brace-expansion": "^1.0.0" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha512-miQKw5Hv4NS1Psg2517mV4e4dYNaO3++hjAvLOAzKqZ61rH8NS1SK+vbfBWZ5PY/Me/bEWhUwqMghEW5Fb9T7Q==", + "dev": true + }, + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + }, + "dependencies": { + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + } + } + }, + "mustache": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.2.1.tgz", + "integrity": "sha1-LEDKIcJ49TFQaCvPkJDkGjM5uHY=", + "dev": true + }, + "node-uuid": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz", + "integrity": "sha1-baWhdmjEs91ZYjvaEc9/pMH2Cm8=", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "nub": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/nub/-/nub-0.0.0.tgz", + "integrity": "sha1-s2m9Mr3eZq9ZYFw7BSC8IZ3MwE8=", + "dev": true + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "dev": true, + "requires": { + "wordwrap": "~0.0.2" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } + }, + "parallelshell": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parallelshell/-/parallelshell-2.0.0.tgz", + "integrity": "sha512-EJJKjVi68lT+1CnuejYfoJdTxoChOIwDjy21bXFrH3YoJjcDR/8MsotXOY6U2p3rDi2BqYNVySAlF0e9B4S6fA==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "dev": true + }, + "phantomjs": { + "version": "1.9.20", + "resolved": "https://registry.npmjs.org/phantomjs/-/phantomjs-1.9.20.tgz", + "integrity": "sha1-RCSsog4U0lXAsIia9va4lz2hDg0=", + "dev": true, + "requires": { + "extract-zip": "~1.5.0", + "fs-extra": "~0.26.4", + "hasha": "^2.2.0", + "kew": "~0.7.0", + "progress": "~1.1.8", + "request": "~2.67.0", + "request-progress": "~2.0.1", + "which": "~1.2.2" + }, + "dependencies": { + "fs-extra": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.7.tgz", + "integrity": "sha1-muH92UiXeY7at20JGM9C0MMYT6k=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + } + } + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkginfo": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.3.1.tgz", + "integrity": "sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=", + "dev": true + }, + "prettysize": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/prettysize/-/prettysize-0.0.3.tgz", + "integrity": "sha1-FK//amReWRpN3xxykZwjtBRhgaE=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qs": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-5.2.1.tgz", + "integrity": "sha512-sh/hmLUTLEiYFhSbRvkM4zj6fMWnbqQt9wrppR2LJA/U/u4xS2eWN8LBE1xc79ExYZJBVZYSMBv/INC7wpE+fw==", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "reconnect": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/reconnect/-/reconnect-0.1.5.tgz", + "integrity": "sha1-3/6iUtYb6/swLsFwzvc9LS52WPI=", + "dev": true, + "requires": { + "backoff": "~1.0.0", + "h": "~0.1.0", + "shoe": "~0.0.7" + } + }, + "request": { + "version": "2.67.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.67.0.tgz", + "integrity": "sha512-fzMRDWVEdMktE3foqvL4CBmC+AR8WvcP8pIPx6JSqqhWuPr+BxX9tKx4XiijfyeKtqqRMNpHDWqFMw4JlRPIJg==", + "dev": true, + "requires": { + "aws-sign2": "~0.6.0", + "bl": "~1.0.0", + "caseless": "~0.11.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~1.0.0-rc3", + "har-validator": "~2.0.2", + "hawk": "~3.1.0", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "node-uuid": "~1.4.7", + "oauth-sign": "~0.8.0", + "qs": "~5.2.0", + "stringstream": "~0.0.4", + "tough-cookie": "~2.2.0", + "tunnel-agent": "~0.4.1" + } + }, + "request-progress": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", + "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", + "dev": true, + "requires": { + "throttleit": "^1.0.0" + } + }, + "resolve": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.2.8.tgz", + "integrity": "sha1-/bF9SrsOyvb4DWesA88pAIj2wNA=", + "dev": true + }, + "rimraf": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.4.tgz", + "integrity": "sha1-loAAk8vxoMhr2VtGJUZ1NcKd+gQ=", + "dev": true, + "requires": { + "glob": "^7.0.5" + }, + "dependencies": { + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sass": { + "version": "1.54.4", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.54.4.tgz", + "integrity": "sha512-3tmF16yvnBwtlPrNBHw/H907j8MlOX8aTBnlNX1yrKx24RKcJGPyLhFUwkoKBKesR3unP93/2z14Ll8NicwQUA==", + "dev": true, + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + } + }, + "sax": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.1.6.tgz", + "integrity": "sha1-XWFr6KXmB9VOEUr65Vt+ry/MMkA=", + "dev": true + }, + "shoe": { + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/shoe/-/shoe-0.0.15.tgz", + "integrity": "sha512-XM5aTvK9kzdYYYZ0sr4pqteQ1jeHucXgSa6ueQE7CrDZTa+1bXGbQWT5EPyIw4LYhZ0fur43cGZgnifJJPfSOQ==", + "dev": true, + "requires": { + "sockjs": "0.3.7" + }, + "dependencies": { + "sockjs-client": { + "version": "0.0.0-unreleasable", + "bundled": true, + "extraneous": true + } + } + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha512-7bgVOAnPj3XjrKY577S+puCKGCRlUrcrEdsMeRXlg9Ghf5df/xNi6sONUa43WrHUd3TjJBF7O04jYoiY0FVa0A==", + "dev": true, + "requires": { + "hoek": "2.x.x" + } + }, + "sockjs": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.7.tgz", + "integrity": "sha512-Hhb9Z0yY5QWc4rSXcGgByUhijT/adjyL6SpoLeZgXbpa8rd2s9Dbr1voP/8eeLDYET4AHTffPxz4kgJQH8WwrA==", + "dev": true, + "requires": { + "faye-websocket": "0.4.4", + "node-uuid": "1.3.3" + }, + "dependencies": { + "node-uuid": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.3.3.tgz", + "integrity": "sha512-xKQtL5imfvX6PvUmgJyU/XaNT/l8tKvs+sJ6KLOmIzk/H8+sm7uE80QlPmmu3l1uirvRL3kZqtJPWoQBWT9gQw==", + "dev": true + } + } + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sshpk": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", + "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + } + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "svg-sprite": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/svg-sprite/-/svg-sprite-1.0.20.tgz", + "integrity": "sha512-6tyuv5GgaG/HkXYCi+DTa2iErgt6KsJgqgpYlGjuz8uNlhGKxAP6PtkNlsea2Zqqmum5Ov1BubQR0kkdA5uUKA==", + "dev": true, + "requires": { + "async": "^0.9.0", + "css-selector-parser": "^1.0.4", + "cssmin": "^0.4.3", + "cssom": "^0.3.0", + "glob": "^5.0.1", + "js-yaml": "^3.2.7", + "lodash": "^3.4.0", + "mkdirp": "^0.5.0", + "mustache": "^2.0.0", + "phantomjs": "^1.9.16", + "prettysize": "^0.0.3", + "svgo": "^0.5.0", + "vinyl": "^0.4.6", + "winston": "^0.9.0", + "xmldom": "^0.1.19", + "xpath": "^0.0.9", + "yargs": "^3.4.5" + } + }, + "svgo": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.5.6.tgz", + "integrity": "sha512-KSiqo2B+gE0Vk7iItrsOmvKOu5o9eZ0fI6oJ3JhemXqIWRVL9KoSIfLIi2xy4gl8nU2kJRjM4n1RnvPmv9ncFA==", + "dev": true, + "requires": { + "coa": "~1.0.1", + "colors": "~1.1.2", + "js-yaml": "~3.3.1", + "mkdirp": "~0.5.1", + "sax": "~1.1.1", + "whet.extend": "~0.9.9" + }, + "dependencies": { + "esprima": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.2.0.tgz", + "integrity": "sha1-QpLB1o5Bc9gV+iKQ3Hr8ltgfzYM=", + "dev": true + }, + "js-yaml": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.3.1.tgz", + "integrity": "sha512-fjgnhG5HijmXtlBCMcU0JyCq/VA8YtdBwFNIBDiu3hpJ5Zsvs7993VC0XNNSiKoM8g399vY+21yqzT/TRS3KMQ==", + "dev": true, + "requires": { + "argparse": "~1.0.2", + "esprima": "~2.2.0" + } + } + } + }, + "syntax-error": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-0.0.1.tgz", + "integrity": "sha512-Pg2FzUaDR1Zlkl5ol+6LGAES7PjqcvfUpa2OKZZhww4VrRyjZyU2v+4C0dcYfhwNl2FMaZW9mXHzX0kS9x3xXw==", + "dev": true, + "requires": { + "esprima": "~0.9.9" + }, + "dependencies": { + "esprima": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-0.9.9.tgz", + "integrity": "sha1-G5CSXJddYy1ygpOcO7nDpCPDBJA=", + "dev": true + } + } + }, + "throttleit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", + "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "to-utf8": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/to-utf8/-/to-utf8-0.0.1.tgz", + "integrity": "sha1-0Xrqcv8vujm55DYBvns/9y4ImFI=", + "dev": true + }, + "tough-cookie": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.2.2.tgz", + "integrity": "sha512-Knz9Yr0hlBoWQgUKzOIvRg5adinizAf49i2gHRhj6cLjlM304zRw7uyiY22ADniDxnPHXfIeyQD0EAkgpIz0ow==", + "dev": true + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha512-e0IoVDWx8SDHc/hwFTqJDQ7CCDTEeGhmcT9jkWJjoGQSpgBz20nAMr80E3Tpk7PatJ1b37DQDgJR3CNSzcMOZQ==", + "dev": true + }, + "tweetnacl": { + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.3.tgz", + "integrity": "sha1-PaOC9nDyXe1417PReSEZvKC3Ey0=", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true + } + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + }, + "vm-browserify": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-0.0.4.tgz", + "integrity": "sha1-XX6kW7755Kb/ZflUOOCofDV9WnM=", + "dev": true, + "requires": { + "indexof": "0.0.1" + } + }, + "watch": { + "version": "0.19.3", + "resolved": "https://registry.npmjs.org/watch/-/watch-0.19.3.tgz", + "integrity": "sha512-foeUUwledbAQMY93TffBBnftHifGqRzB9QbJC5FjuRuTyUQJLDfZUedxlarZr/oGvCQM3LpVXg7HGEe8syPVow==", + "dev": true, + "requires": { + "exec-sh": "^0.2.0", + "minimist": "^1.2.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + } + } + }, + "watchr": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/watchr/-/watchr-2.1.6.tgz", + "integrity": "sha1-bciVv2yVq29eBtgRlIsyCphBOJE=", + "dev": true, + "requires": { + "bal-util": "1.13.x" + } + }, + "whet.extend": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", + "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=", + "dev": true + }, + "which": { + "version": "1.2.12", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.12.tgz", + "integrity": "sha1-3me15FAmnxlJCe8j7OTr5Bb6EZI=", + "dev": true, + "requires": { + "isexe": "^1.1.1" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", + "dev": true + }, + "winston": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-0.9.0.tgz", + "integrity": "sha1-tXJubEIpHjBeNihs566fO3SlJ6g=", + "dev": true, + "requires": { + "async": "0.9.x", + "colors": "1.0.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "isstream": "0.1.x", + "pkginfo": "0.3.x", + "stack-trace": "0.0.x" + }, + "dependencies": { + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + } + } + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xmldom": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", + "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==", + "dev": true + }, + "xpath": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.9.tgz", + "integrity": "sha1-s57qHq+9yOzdohrUkcjbQPAT+1Q=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "y18n": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==", + "dev": true + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "dev": true, + "requires": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" + } + }, + "yauzl": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", + "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", + "dev": true, + "requires": { + "fd-slicer": "~1.0.1" + } + } + } +} diff --git a/package.json b/package.json index 0e9a83dd..4d80615e 100644 --- a/package.json +++ b/package.json @@ -2,13 +2,13 @@ "name": "docs.modmore.com", "version": "1.0.0", "private": true, - "dependencies": { + "devDependencies": { "bower": "1.x.x", "esprima": "^3.1.0", "jshint": "latest", "live-reload": "1.x.x", "mkdirp": "^0.5.1", - "npm-build-tools": "christianseel/npm-build-tools", + "sass": "^1.32.8", "parallelshell": "2.0.x", "rimraf": "latest", "svg-sprite": "1.0.x", @@ -19,7 +19,8 @@ "lint": "jshint src/js", "prebuild:js": "npm run lint", "build:js": "node node_modules/npm-build-tools/index.js --path \"src/js/\" --ext \"js\" --outputDir \"themes/modmore/dist/\"", - "build:css": "node node_modules/npm-build-tools/index.js --path \"src/scss/\" --ext \"scss\" --outputDir \"themes/modmore/dist/\" --outputStyle \"compressed\" --browsers \"['> 2%', 'last 2 versions', 'ie >= 9', 'and_chr >= 2.3']\"", + "build:css": "sass --style=compressed src/scss:themes/modmore/dist", + "build:cssss": "node node_modules/npm-build-tools/index.js --path \"src/scss/\" --ext \"scss\" --outputDir \"themes/modmore/dist/\" --outputStyle \"compressed\" --browsers \"['> 2%', 'last 2 versions', 'ie >= 9', 'and_chr >= 2.3']\"", "build:svg": "svg-sprite --symbol --symbol-dest themes/modmore/dist --symbol-sprite sprite.svg src/svg/*.svg", "build": "npm run build:js && npm run build:css && npm run build:svg", "watch": "parallelshell \"npm run watch:css\" \"npm run watch:js\" \"npm run watch:svg\"", @@ -29,9 +30,5 @@ "gitify": "watch \"Gitify build\" _gitify", "live-reload": "live-reload --port 9091 --delay 1000 themes/modmore/dist/", "start": "npm run live-reload -s & npm run watch -s" - }, - "devDependencies": { - "node-sass": "^3.10.1", - "node-uuid": "^1.4.7" } } diff --git a/src/bower_components/foundation-sites/scss/components/_table.scss b/src/bower_components/foundation-sites/scss/components/_table.scss index b3b1be8e..bd4f5ff2 100644 --- a/src/bower_components/foundation-sites/scss/components/_table.scss +++ b/src/bower_components/foundation-sites/scss/components/_table.scss @@ -197,7 +197,7 @@ $show-header-for-stacked: false !default; } //Darkens the odd striped table rows. - @elseif($table-stripe == odd) { + @else if($table-stripe == odd) { &:nth-of-type(odd):hover { background-color: $table-row-stripe-hover; } diff --git a/src/scss/_pagecontent.scss b/src/scss/_pagecontent.scss index 02b303c3..fe7ef8e4 100644 --- a/src/scss/_pagecontent.scss +++ b/src/scss/_pagecontent.scss @@ -11,6 +11,20 @@ h1,h2,h3,h4,h5,h6 { text-rendering: $header-text-rendering; color: $primary-color; } +h1, h2 { + margin-top: 2rem; +} +h2 { + border-bottom: 2px solid #d2e3ee; +} +h3, h4, h5, h6 { + padding-left: 1rem; + margin-bottom: 0.5rem; + + &.TableOfContentsContainer__title { + padding-left: 0; + } +} @for $i from 1 through 6 { h#{$i} { @@ -24,7 +38,7 @@ h1 { p, td, th { margin: 0 0 $paragraph-margin-bottom; - font-size: rem(15); + font-size: rem(16); line-height: $paragraph-lineheight; text-rendering: $paragraph-text-rendering; } @@ -61,4 +75,46 @@ table { th { border-bottom-width: 2px; } -} \ No newline at end of file +} + +code, kbd, samp { + background: #fdf6e3; + color: #365661; + padding: 0.25em; +} + +blockquote { + background: #f7fafc; + padding: 1em 1.2em .95em; + border-radius: 4px; + border: 1px solid #d2e3ee; + border-left-width: 5px; + box-shadow: 0 0 3px rgba(39,44,49,.02),0 5px 22px -6px rgba(39,44,49,.05); + + margin-left: 0; + margin-right: 0; + + :last-child { + margin-bottom: 0; + } +} + +.alert { + background: #f7fafc; + padding: 1em 1.2em .95em; + border-radius: 4px; + border: 1px solid #d2e3ee; + box-shadow: 0 0 3px rgba(39,44,49,.02),0 5px 22px -6px rgba(39,44,49,.05); + margin-bottom: 1em; + + :last-child { + margin-bottom: 0; + } +} +.Permalink { + margin-left: -1em; + width: 1em; + display: inline-block; + text-align: center; + text-decoration: none !important; +} diff --git a/src/scss/_pageheader.scss b/src/scss/_pageheader.scss index 3492cdf0..c164c72a 100644 --- a/src/scss/_pageheader.scss +++ b/src/scss/_pageheader.scss @@ -1,4 +1,4 @@ -$pageheader-color: $body-background; +$pageheader-color: #fff; $pageheader-font-color: #555; .pageheader { height: rem(57); @@ -7,7 +7,7 @@ $pageheader-font-color: #555; flex-direction: row; flex-wrap: nowrap; justify-content: space-between; - padding: rem(0 30); + padding: rem(0 30 0 0); color: $pageheader-font-color; background: $pageheader-color; @@ -29,7 +29,7 @@ $pageheader-font-color: #555; top: 0; left: 0; right: 0; - padding: rem(0 45); + padding: rem(0 45 0 0); } } @@ -79,4 +79,4 @@ form.docsearch { max-height: rem(24); } } -} \ No newline at end of file +} diff --git a/src/scss/_settings.scss b/src/scss/_settings.scss index 8766e9ce..769d3c9a 100644 --- a/src/scss/_settings.scss +++ b/src/scss/_settings.scss @@ -45,7 +45,7 @@ $global-font-size: 100%; $body-font-size: 100%; -$global-width: rem-calc(664); +$global-width: rem-calc(708); $global-lineheight: 1.5; $foundation-palette: ( primary: #1f4a7f, @@ -500,7 +500,7 @@ $table-row-hover: darken($table-background, $table-hover-scale); $table-row-stripe-hover: darken($table-background, $table-color-scale + $table-hover-scale); $table-striped-background: smart-scale($table-background, $table-color-scale); $table-stripe: even; -$table-head-background: smart-scale($table-background, $table-color-scale / 2); +$table-head-background: smart-scale($table-background, $table-color-scale * 0.5); $table-foot-background: smart-scale($table-background, $table-color-scale); $table-head-font-color: $body-font-color; $table-foot-font-color: $body-font-color; @@ -563,4 +563,4 @@ $topbar-background: $light-gray; $topbar-submenu-background: $topbar-background; $topbar-title-spacing: 1rem; $topbar-input-width: 200px; -$topbar-unstack-breakpoint: medium; \ No newline at end of file +$topbar-unstack-breakpoint: medium; diff --git a/src/scss/_sidebar.scss b/src/scss/_sidebar.scss index ddf423ab..95c5c72f 100644 --- a/src/scss/_sidebar.scss +++ b/src/scss/_sidebar.scss @@ -4,7 +4,7 @@ aside.sidebar { text-shadow: 0 0 rem(15) rgba(0,0,0,0.15); @include breakpoint(large) { - border-right: 3px solid #132843; + //border-right: 3px solid #132843; } } @@ -180,9 +180,9 @@ nav.pagenav { // 2nd level link > ul > li > ul > li > a { - padding-left: rem(45); - font-size: rem(12); - text-transform: uppercase; + padding-left: rem(30); + font-size: rem(14); + //text-transform: uppercase; //background-image: #{"url(\"data:image/svg+xml;charset=UTF-8,\")"}; // background-size: rem(13); //background-repeat: no-repeat; @@ -193,8 +193,8 @@ nav.pagenav { // 3rd level link li li li a { - padding-left: rem(60); - font-size: rem(12); + padding-left: rem(45); + font-size: rem(14); font-weight: $global-weight-normal; } @@ -262,4 +262,4 @@ nav.pagenav .Nav__item--open>a { margin-left: -20px; width: 16px; margin-right: 4px; -} \ No newline at end of file +} diff --git a/src/scss/_template.scss b/src/scss/_template.scss index c731f8d1..81084362 100644 --- a/src/scss/_template.scss +++ b/src/scss/_template.scss @@ -5,10 +5,11 @@ html, body { background: $body-background; } body { - visibility: visible; - opacity: 1; - -webkit-font-smoothing: antialiased; - font-size: $body-font-size; + visibility: visible; + opacity: 1; + -webkit-font-smoothing: antialiased; + font-size: $body-font-size; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; } * { @@ -52,12 +53,10 @@ body { position: absolute; top: 0; right: 0; - left: rem(300); + left: rem(350); width: auto; - left: auto; padding-top: rem(56); - padding-right: calc((100% - #{rem(1024)})/2); - width: rem(724); + padding-right: calc((100% - #{rem(1280)})/2); } } @@ -78,7 +77,7 @@ aside.sidebar { left: 0; width: rem(300); height: 100%; - padding-left: calc((100% - #{rem(1024)})/2); + padding-left: rem(50); } } @@ -86,4 +85,4 @@ aside.sidebar { p { font-size: $small-font-size; } -} \ No newline at end of file +} diff --git a/src/scss/_tipuesearch.scss b/src/scss/_tipuesearch.scss index 976c3c36..117cd557 100644 --- a/src/scss/_tipuesearch.scss +++ b/src/scss/_tipuesearch.scss @@ -1,151 +1,212 @@ /* JavaScript powered tipuesearch */ -#tipue_search_warning { - font-weight:300; - font-size:15px; - line-height: 1.6; - color: #555; - margin: 7px 0; -} - -#tipue_search_warning a { - color: #396; - text-decoration: none; -} - -#tipue_search_warning a:hover { - color: #555; -} - -#tipue_search_results_count { - font-weight:300; - font-size:15px; - line-height: 1.7; - color: #555; -} - -.tipue_search_content_title { - font-weight:300; - font-size:21px; - line-height: 1.7; - margin-top: 23px; -} - -.tipue_search_content_title a { - color: #333; - text-decoration: none; -} - -.tipue_search_content_title a:hover { - color: #555; -} - -.tipue_search_content_url { - font-weight:300; - font-size:14px; - line-height: 1.9; - word-wrap: break-word; - hyphens: auto; -} - -.tipue_search_content_url a { - color: #396; - text-decoration: none; -} - -.tipue_search_content_url a:hover { - color: #555; -} - -.tipue_search_content_text { - font-weight:300; - font-size:15px; - line-height: 1.6; - color: #555; - word-wrap: break-word; - hyphens: auto; - margin-top: 3px; -} - -.tipue_search_content_debug { - font-weight:300; - font-size:13px; - line-height: 1.6; - color: #555; - margin: 5px 0; -} -.h01 { - color: #333; - font-weight: 400; -} - -#tipue_search_foot { - margin: 51px 0 21px 0; - padding: 0 10px; -} - -#tipue_search_foot_boxes li { - margin: 0 4px; -} - -#tipue_search_foot_boxes li.current { - display: inline-block; - padding: 5px 14px; - border-radius: 15px; - - color: #333; - background: #f6f6f6; - border: 1px solid #e2e2e2; -} - - -/* spinner */ - -.tipue_search_spinner { - padding: 31px 0; - width: 50px; - height: 28px; -} - -.tipue_search_spinner > div { - background-color: #777; - height: 100%; - width: 3px; - display: inline-block; - margin-right: 2px; - -webkit-animation: stretchdelay 1.2s infinite ease-in-out; - animation: stretchdelay 1.2s infinite ease-in-out; -} - -.tipue_search_spinner .tipue_search_rect2 { - -webkit-animation-delay: -1.1s; - animation-delay: -1.1s; -} - -.tipue_search_spinner .tipue_search_rect3 { - -webkit-animation-delay: -1.0s; - animation-delay: -1.0s; -} - -@-webkit-keyframes stretchdelay { - 0%, 40%, 100% { - -webkit-transform: scaleY(0.4) +.Search { + position: relative; + width: 100%; + + &__field { + display: block; + width: 100%; + height: 55px; + padding: 12px 30px 6px 50px; + //color: var(--search-field-color); + border-width: 0 0 1px; + border-bottom: 1px solid var(--search-field-border-color); + //background: var(--search-field-background); + transition: border-color ease-in-out 0.15s; + + &:focus { + border-color: var(--search-field-hover-border-color); + outline: 0; // stylelint-disable-line plugin/no-unsupported-browser-features + } } - 20% { - -webkit-transform: scaleY(1.0) + + &__icon { + position: absolute; + left: 20px; + top: 20px; + width: 18px; + height: 18px; + cursor: pointer; } } -@keyframes stretchdelay { - 0%, 40%, 100% { - transform: scaleY(0.4); - -webkit-transform: scaleY(0.4); - } - 20% { - transform: scaleY(1.0); - -webkit-transform: scaleY(1.0); +.Navbar .Search { + float: right; + margin: 8px 20px; + + &__field { + box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075); + border-width: 0; + border-radius: 4px; + padding-left: 10px; } } +.SearchResults .Search__field { + height: 1em; + background: #f7fafc; + padding: 1em; + border-radius: 4px; + border: 1px solid #d2e3ee; + box-shadow: 0 0 3px rgba(39,44,49,.02),0 5px 22px -6px rgba(39,44,49,.05); +} + +.SearchResults__close { + line-height: 1em; + margin-right: 0.25em; +} +.SearchResults__count { + margin-top: 0.25em; +} + +//#tipue_search_warning { +// font-weight:300; +// font-size:15px; +// line-height: 1.6; +// color: #555; +// margin: 7px 0; +//} +// +//#tipue_search_warning a { +// color: #396; +// text-decoration: none; +//} +// +//#tipue_search_warning a:hover { +// color: #555; +//} +// +//#tipue_search_results_count { +// font-weight:300; +// font-size:15px; +// line-height: 1.7; +// color: #555; +//} +// +//.tipue_search_content_title { +// font-weight:300; +// font-size:21px; +// line-height: 1.7; +// margin-top: 23px; +//} +// +//.tipue_search_content_title a { +// color: #333; +// text-decoration: none; +//} +// +//.tipue_search_content_title a:hover { +// color: #555; +//} +// +//.tipue_search_content_url { +// font-weight:300; +// font-size:14px; +// line-height: 1.9; +// word-wrap: break-word; +// hyphens: auto; +//} +// +//.tipue_search_content_url a { +// color: #396; +// text-decoration: none; +//} +// +//.tipue_search_content_url a:hover { +// color: #555; +//} +// +//.tipue_search_content_text { +// font-weight:300; +// font-size:15px; +// line-height: 1.6; +// color: #555; +// word-wrap: break-word; +// hyphens: auto; +// margin-top: 3px; +//} +// +//.tipue_search_content_debug { +// font-weight:300; +// font-size:13px; +// line-height: 1.6; +// color: #555; +// margin: 5px 0; +//} +// +//.h01 { +// color: #333; +// font-weight: 400; +//} +// +//#tipue_search_foot { +// margin: 51px 0 21px 0; +// padding: 0 10px; +//} +// +//#tipue_search_foot_boxes li { +// margin: 0 4px; +//} +// +//#tipue_search_foot_boxes li.current { +// display: inline-block; +// padding: 5px 14px; +// border-radius: 15px; +// +// color: #333; +// background: #f6f6f6; +// border: 1px solid #e2e2e2; +//} +// +// +///* spinner */ +// +//.tipue_search_spinner { +// padding: 31px 0; +// width: 50px; +// height: 28px; +//} +// +//.tipue_search_spinner > div { +// background-color: #777; +// height: 100%; +// width: 3px; +// display: inline-block; +// margin-right: 2px; +// -webkit-animation: stretchdelay 1.2s infinite ease-in-out; +// animation: stretchdelay 1.2s infinite ease-in-out; +//} +// +//.tipue_search_spinner .tipue_search_rect2 { +// -webkit-animation-delay: -1.1s; +// animation-delay: -1.1s; +//} +// +//.tipue_search_spinner .tipue_search_rect3 { +// -webkit-animation-delay: -1.0s; +// animation-delay: -1.0s; +//} +// +//@-webkit-keyframes stretchdelay { +// 0%, 40%, 100% { +// -webkit-transform: scaleY(0.4) +// } +// 20% { +// -webkit-transform: scaleY(1.0) +// } +//} +// +//@keyframes stretchdelay { +// 0%, 40%, 100% { +// transform: scaleY(0.4); +// -webkit-transform: scaleY(0.4); +// } +// 20% { +// transform: scaleY(1.0); +// -webkit-transform: scaleY(1.0); +// } +//} +// diff --git a/src/scss/main.scss b/src/scss/main.scss index aa4b0feb..cfc17bc4 100644 --- a/src/scss/main.scss +++ b/src/scss/main.scss @@ -91,9 +91,10 @@ aside.sidebar { max-width: 100%; } .s-content li { - font-size: .875rem; + font-size: 1em; line-height: 1.6; text-rendering: optimizeLegibility; + margin-bottom: 0.4em; } .s-content li > p:last-of-type { margin-bottom: 0; @@ -137,4 +138,41 @@ aside.sidebar { } .Pager--prev>a { float: left -} \ No newline at end of file +} + + +.u-visuallyHidden { + position: absolute !important; + height: 1px; + width: 1px; + overflow: hidden; + clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ + clip: rect(1px, 1px, 1px, 1px); + white-space: nowrap; /* added line */ +} + +.s-content a { + font-weight: 600; + text-decoration: underline; + + &.Link--external { + white-space: nowrap; + &:after { + content: " " url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAVklEQVR4Xn3PgQkAMQhDUXfqTu7kTtkpd5RA8AInfArtQ2iRXFWT2QedAfttj2FsPIOE1eCOlEuoWWjgzYaB/IkeGOrxXhqB+uA9Bfcm0lAZuh+YIeAD+cAqSz4kCMUAAAAASUVORK5CYII=); + } + } + + &.Link--broken { + color: red; + } +} + +.s-content table { + min-width: 100%; + margin-bottom: 1em; + + @include breakpoint(large) { + margin-left: -2.5em; + margin-right: -2.5em; + } +} diff --git a/themes/modmore/config.json b/themes/modmore/config.json index ade0bb6c..ee65019a 100644 --- a/themes/modmore/config.json +++ b/themes/modmore/config.json @@ -2,5 +2,5 @@ "favicon": "img/favicon.png", "fonts": ["https://fonts.googleapis.com/css?family=Roboto+Slab:400,100,300,700&subset=latin,cyrillic-ext,cyrillic"], "js": ["dist/head.js","dist/main.js","dist/images.js"], - "css": ["dist/main.css?v=2"] + "css": ["dist/main.css?v=2.2"] } diff --git a/themes/modmore/dist/critical.css b/themes/modmore/dist/critical.css index 89cc493b..8e245920 100644 --- a/themes/modmore/dist/critical.css +++ b/themes/modmore/dist/critical.css @@ -1,2 +1 @@ -body{visibility:hidden;opacity:0} -/*# sourceMappingURL=critical.css.map */ \ No newline at end of file +body{visibility:hidden;opacity:0}/*# sourceMappingURL=critical.css.map */ diff --git a/themes/modmore/dist/critical.css.map b/themes/modmore/dist/critical.css.map index 7733fc34..60676215 100644 --- a/themes/modmore/dist/critical.css.map +++ b/themes/modmore/dist/critical.css.map @@ -1,9 +1 @@ -{ - "version": 3, - "file": "critical.css", - "sources": [ - "../../../src/scss/critical.scss" - ], - "mappings": "AACA,AAAA,IAAI,AAAA,CACA,UAAU,CAAE,MAAO,CACnB,OAAO,CAAE,CAAE,CACd", - "names": [] -} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["../../../src/scss/critical.scss"],"names":[],"mappings":"AACA,KACI,kBACA","file":"critical.css"} \ No newline at end of file diff --git a/themes/modmore/dist/main.css b/themes/modmore/dist/main.css index 8a075cb4..6b325ea6 100644 --- a/themes/modmore/dist/main.css +++ b/themes/modmore/dist/main.css @@ -1,2 +1 @@ -@-ms-viewport{width:device-width}/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:0.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace, monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace, monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,html [type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-cancel-button,[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}.row{max-width:41.5rem;margin-left:auto;margin-right:auto}.row::before,.row::after{content:' ';display:table}.row::after{clear:both}.row.collapse>.column,.row.collapse>.columns{padding-left:0;padding-right:0}.row .row{margin-left:-.625rem;margin-right:-.625rem}@media screen and (min-width: 40em){.row .row{margin-left:-.9375rem;margin-right:-.9375rem}}.row .row.collapse{margin-left:0;margin-right:0}.row.expanded{max-width:none}.row.expanded .row{margin-left:auto;margin-right:auto}.column,.columns{width:100%;float:left;padding-left:.625rem;padding-right:.625rem}@media screen and (min-width: 40em){.column,.columns{padding-left:.9375rem;padding-right:.9375rem}}.column:last-child:not(:first-child),.columns:last-child:not(:first-child){float:right}.column.end:last-child:last-child,.end.columns:last-child:last-child{float:left}.column.row.row,.row.row.columns{float:none}.row .column.row.row,.row .row.row.columns{padding-left:0;padding-right:0;margin-left:0;margin-right:0}.small-1{width:8.33333%}.small-push-1{position:relative;left:8.33333%}.small-pull-1{position:relative;left:-8.33333%}.small-offset-0{margin-left:0%}.small-2{width:16.66667%}.small-push-2{position:relative;left:16.66667%}.small-pull-2{position:relative;left:-16.66667%}.small-offset-1{margin-left:8.33333%}.small-3{width:25%}.small-push-3{position:relative;left:25%}.small-pull-3{position:relative;left:-25%}.small-offset-2{margin-left:16.66667%}.small-4{width:33.33333%}.small-push-4{position:relative;left:33.33333%}.small-pull-4{position:relative;left:-33.33333%}.small-offset-3{margin-left:25%}.small-5{width:41.66667%}.small-push-5{position:relative;left:41.66667%}.small-pull-5{position:relative;left:-41.66667%}.small-offset-4{margin-left:33.33333%}.small-6{width:50%}.small-push-6{position:relative;left:50%}.small-pull-6{position:relative;left:-50%}.small-offset-5{margin-left:41.66667%}.small-7{width:58.33333%}.small-push-7{position:relative;left:58.33333%}.small-pull-7{position:relative;left:-58.33333%}.small-offset-6{margin-left:50%}.small-8{width:66.66667%}.small-push-8{position:relative;left:66.66667%}.small-pull-8{position:relative;left:-66.66667%}.small-offset-7{margin-left:58.33333%}.small-9{width:75%}.small-push-9{position:relative;left:75%}.small-pull-9{position:relative;left:-75%}.small-offset-8{margin-left:66.66667%}.small-10{width:83.33333%}.small-push-10{position:relative;left:83.33333%}.small-pull-10{position:relative;left:-83.33333%}.small-offset-9{margin-left:75%}.small-11{width:91.66667%}.small-push-11{position:relative;left:91.66667%}.small-pull-11{position:relative;left:-91.66667%}.small-offset-10{margin-left:83.33333%}.small-12{width:100%}.small-offset-11{margin-left:91.66667%}.small-up-1>.column,.small-up-1>.columns{width:100%;float:left}.small-up-1>.column:nth-of-type(1n),.small-up-1>.columns:nth-of-type(1n){clear:none}.small-up-1>.column:nth-of-type(1n+1),.small-up-1>.columns:nth-of-type(1n+1){clear:both}.small-up-1>.column:last-child,.small-up-1>.columns:last-child{float:left}.small-up-2>.column,.small-up-2>.columns{width:50%;float:left}.small-up-2>.column:nth-of-type(1n),.small-up-2>.columns:nth-of-type(1n){clear:none}.small-up-2>.column:nth-of-type(2n+1),.small-up-2>.columns:nth-of-type(2n+1){clear:both}.small-up-2>.column:last-child,.small-up-2>.columns:last-child{float:left}.small-up-3>.column,.small-up-3>.columns{width:33.33333%;float:left}.small-up-3>.column:nth-of-type(1n),.small-up-3>.columns:nth-of-type(1n){clear:none}.small-up-3>.column:nth-of-type(3n+1),.small-up-3>.columns:nth-of-type(3n+1){clear:both}.small-up-3>.column:last-child,.small-up-3>.columns:last-child{float:left}.small-up-4>.column,.small-up-4>.columns{width:25%;float:left}.small-up-4>.column:nth-of-type(1n),.small-up-4>.columns:nth-of-type(1n){clear:none}.small-up-4>.column:nth-of-type(4n+1),.small-up-4>.columns:nth-of-type(4n+1){clear:both}.small-up-4>.column:last-child,.small-up-4>.columns:last-child{float:left}.small-up-5>.column,.small-up-5>.columns{width:20%;float:left}.small-up-5>.column:nth-of-type(1n),.small-up-5>.columns:nth-of-type(1n){clear:none}.small-up-5>.column:nth-of-type(5n+1),.small-up-5>.columns:nth-of-type(5n+1){clear:both}.small-up-5>.column:last-child,.small-up-5>.columns:last-child{float:left}.small-up-6>.column,.small-up-6>.columns{width:16.66667%;float:left}.small-up-6>.column:nth-of-type(1n),.small-up-6>.columns:nth-of-type(1n){clear:none}.small-up-6>.column:nth-of-type(6n+1),.small-up-6>.columns:nth-of-type(6n+1){clear:both}.small-up-6>.column:last-child,.small-up-6>.columns:last-child{float:left}.small-up-7>.column,.small-up-7>.columns{width:14.28571%;float:left}.small-up-7>.column:nth-of-type(1n),.small-up-7>.columns:nth-of-type(1n){clear:none}.small-up-7>.column:nth-of-type(7n+1),.small-up-7>.columns:nth-of-type(7n+1){clear:both}.small-up-7>.column:last-child,.small-up-7>.columns:last-child{float:left}.small-up-8>.column,.small-up-8>.columns{width:12.5%;float:left}.small-up-8>.column:nth-of-type(1n),.small-up-8>.columns:nth-of-type(1n){clear:none}.small-up-8>.column:nth-of-type(8n+1),.small-up-8>.columns:nth-of-type(8n+1){clear:both}.small-up-8>.column:last-child,.small-up-8>.columns:last-child{float:left}.small-collapse>.column,.small-collapse>.columns{padding-left:0;padding-right:0}.small-collapse .row{margin-left:0;margin-right:0}.expanded.row .small-collapse.row{margin-left:0;margin-right:0}.small-uncollapse>.column,.small-uncollapse>.columns{padding-left:.625rem;padding-right:.625rem}.small-centered{margin-left:auto;margin-right:auto}.small-centered,.small-centered:last-child:not(:first-child){float:none;clear:both}.small-uncentered,.small-push-0,.small-pull-0{position:static;margin-left:0;margin-right:0;float:left}@media screen and (min-width: 40em){.medium-1{width:8.33333%}.medium-push-1{position:relative;left:8.33333%}.medium-pull-1{position:relative;left:-8.33333%}.medium-offset-0{margin-left:0%}.medium-2{width:16.66667%}.medium-push-2{position:relative;left:16.66667%}.medium-pull-2{position:relative;left:-16.66667%}.medium-offset-1{margin-left:8.33333%}.medium-3{width:25%}.medium-push-3{position:relative;left:25%}.medium-pull-3{position:relative;left:-25%}.medium-offset-2{margin-left:16.66667%}.medium-4{width:33.33333%}.medium-push-4{position:relative;left:33.33333%}.medium-pull-4{position:relative;left:-33.33333%}.medium-offset-3{margin-left:25%}.medium-5{width:41.66667%}.medium-push-5{position:relative;left:41.66667%}.medium-pull-5{position:relative;left:-41.66667%}.medium-offset-4{margin-left:33.33333%}.medium-6{width:50%}.medium-push-6{position:relative;left:50%}.medium-pull-6{position:relative;left:-50%}.medium-offset-5{margin-left:41.66667%}.medium-7{width:58.33333%}.medium-push-7{position:relative;left:58.33333%}.medium-pull-7{position:relative;left:-58.33333%}.medium-offset-6{margin-left:50%}.medium-8{width:66.66667%}.medium-push-8{position:relative;left:66.66667%}.medium-pull-8{position:relative;left:-66.66667%}.medium-offset-7{margin-left:58.33333%}.medium-9{width:75%}.medium-push-9{position:relative;left:75%}.medium-pull-9{position:relative;left:-75%}.medium-offset-8{margin-left:66.66667%}.medium-10{width:83.33333%}.medium-push-10{position:relative;left:83.33333%}.medium-pull-10{position:relative;left:-83.33333%}.medium-offset-9{margin-left:75%}.medium-11{width:91.66667%}.medium-push-11{position:relative;left:91.66667%}.medium-pull-11{position:relative;left:-91.66667%}.medium-offset-10{margin-left:83.33333%}.medium-12{width:100%}.medium-offset-11{margin-left:91.66667%}.medium-up-1>.column,.medium-up-1>.columns{width:100%;float:left}.medium-up-1>.column:nth-of-type(1n),.medium-up-1>.columns:nth-of-type(1n){clear:none}.medium-up-1>.column:nth-of-type(1n+1),.medium-up-1>.columns:nth-of-type(1n+1){clear:both}.medium-up-1>.column:last-child,.medium-up-1>.columns:last-child{float:left}.medium-up-2>.column,.medium-up-2>.columns{width:50%;float:left}.medium-up-2>.column:nth-of-type(1n),.medium-up-2>.columns:nth-of-type(1n){clear:none}.medium-up-2>.column:nth-of-type(2n+1),.medium-up-2>.columns:nth-of-type(2n+1){clear:both}.medium-up-2>.column:last-child,.medium-up-2>.columns:last-child{float:left}.medium-up-3>.column,.medium-up-3>.columns{width:33.33333%;float:left}.medium-up-3>.column:nth-of-type(1n),.medium-up-3>.columns:nth-of-type(1n){clear:none}.medium-up-3>.column:nth-of-type(3n+1),.medium-up-3>.columns:nth-of-type(3n+1){clear:both}.medium-up-3>.column:last-child,.medium-up-3>.columns:last-child{float:left}.medium-up-4>.column,.medium-up-4>.columns{width:25%;float:left}.medium-up-4>.column:nth-of-type(1n),.medium-up-4>.columns:nth-of-type(1n){clear:none}.medium-up-4>.column:nth-of-type(4n+1),.medium-up-4>.columns:nth-of-type(4n+1){clear:both}.medium-up-4>.column:last-child,.medium-up-4>.columns:last-child{float:left}.medium-up-5>.column,.medium-up-5>.columns{width:20%;float:left}.medium-up-5>.column:nth-of-type(1n),.medium-up-5>.columns:nth-of-type(1n){clear:none}.medium-up-5>.column:nth-of-type(5n+1),.medium-up-5>.columns:nth-of-type(5n+1){clear:both}.medium-up-5>.column:last-child,.medium-up-5>.columns:last-child{float:left}.medium-up-6>.column,.medium-up-6>.columns{width:16.66667%;float:left}.medium-up-6>.column:nth-of-type(1n),.medium-up-6>.columns:nth-of-type(1n){clear:none}.medium-up-6>.column:nth-of-type(6n+1),.medium-up-6>.columns:nth-of-type(6n+1){clear:both}.medium-up-6>.column:last-child,.medium-up-6>.columns:last-child{float:left}.medium-up-7>.column,.medium-up-7>.columns{width:14.28571%;float:left}.medium-up-7>.column:nth-of-type(1n),.medium-up-7>.columns:nth-of-type(1n){clear:none}.medium-up-7>.column:nth-of-type(7n+1),.medium-up-7>.columns:nth-of-type(7n+1){clear:both}.medium-up-7>.column:last-child,.medium-up-7>.columns:last-child{float:left}.medium-up-8>.column,.medium-up-8>.columns{width:12.5%;float:left}.medium-up-8>.column:nth-of-type(1n),.medium-up-8>.columns:nth-of-type(1n){clear:none}.medium-up-8>.column:nth-of-type(8n+1),.medium-up-8>.columns:nth-of-type(8n+1){clear:both}.medium-up-8>.column:last-child,.medium-up-8>.columns:last-child{float:left}.medium-collapse>.column,.medium-collapse>.columns{padding-left:0;padding-right:0}.medium-collapse .row{margin-left:0;margin-right:0}.expanded.row .medium-collapse.row{margin-left:0;margin-right:0}.medium-uncollapse>.column,.medium-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem}.medium-centered{margin-left:auto;margin-right:auto}.medium-centered,.medium-centered:last-child:not(:first-child){float:none;clear:both}.medium-uncentered,.medium-push-0,.medium-pull-0{position:static;margin-left:0;margin-right:0;float:left}}@media screen and (min-width: 64em){.large-1{width:8.33333%}.large-push-1{position:relative;left:8.33333%}.large-pull-1{position:relative;left:-8.33333%}.large-offset-0{margin-left:0%}.large-2{width:16.66667%}.large-push-2{position:relative;left:16.66667%}.large-pull-2{position:relative;left:-16.66667%}.large-offset-1{margin-left:8.33333%}.large-3{width:25%}.large-push-3{position:relative;left:25%}.large-pull-3{position:relative;left:-25%}.large-offset-2{margin-left:16.66667%}.large-4{width:33.33333%}.large-push-4{position:relative;left:33.33333%}.large-pull-4{position:relative;left:-33.33333%}.large-offset-3{margin-left:25%}.large-5{width:41.66667%}.large-push-5{position:relative;left:41.66667%}.large-pull-5{position:relative;left:-41.66667%}.large-offset-4{margin-left:33.33333%}.large-6{width:50%}.large-push-6{position:relative;left:50%}.large-pull-6{position:relative;left:-50%}.large-offset-5{margin-left:41.66667%}.large-7{width:58.33333%}.large-push-7{position:relative;left:58.33333%}.large-pull-7{position:relative;left:-58.33333%}.large-offset-6{margin-left:50%}.large-8{width:66.66667%}.large-push-8{position:relative;left:66.66667%}.large-pull-8{position:relative;left:-66.66667%}.large-offset-7{margin-left:58.33333%}.large-9{width:75%}.large-push-9{position:relative;left:75%}.large-pull-9{position:relative;left:-75%}.large-offset-8{margin-left:66.66667%}.large-10{width:83.33333%}.large-push-10{position:relative;left:83.33333%}.large-pull-10{position:relative;left:-83.33333%}.large-offset-9{margin-left:75%}.large-11{width:91.66667%}.large-push-11{position:relative;left:91.66667%}.large-pull-11{position:relative;left:-91.66667%}.large-offset-10{margin-left:83.33333%}.large-12{width:100%}.large-offset-11{margin-left:91.66667%}.large-up-1>.column,.large-up-1>.columns{width:100%;float:left}.large-up-1>.column:nth-of-type(1n),.large-up-1>.columns:nth-of-type(1n){clear:none}.large-up-1>.column:nth-of-type(1n+1),.large-up-1>.columns:nth-of-type(1n+1){clear:both}.large-up-1>.column:last-child,.large-up-1>.columns:last-child{float:left}.large-up-2>.column,.large-up-2>.columns{width:50%;float:left}.large-up-2>.column:nth-of-type(1n),.large-up-2>.columns:nth-of-type(1n){clear:none}.large-up-2>.column:nth-of-type(2n+1),.large-up-2>.columns:nth-of-type(2n+1){clear:both}.large-up-2>.column:last-child,.large-up-2>.columns:last-child{float:left}.large-up-3>.column,.large-up-3>.columns{width:33.33333%;float:left}.large-up-3>.column:nth-of-type(1n),.large-up-3>.columns:nth-of-type(1n){clear:none}.large-up-3>.column:nth-of-type(3n+1),.large-up-3>.columns:nth-of-type(3n+1){clear:both}.large-up-3>.column:last-child,.large-up-3>.columns:last-child{float:left}.large-up-4>.column,.large-up-4>.columns{width:25%;float:left}.large-up-4>.column:nth-of-type(1n),.large-up-4>.columns:nth-of-type(1n){clear:none}.large-up-4>.column:nth-of-type(4n+1),.large-up-4>.columns:nth-of-type(4n+1){clear:both}.large-up-4>.column:last-child,.large-up-4>.columns:last-child{float:left}.large-up-5>.column,.large-up-5>.columns{width:20%;float:left}.large-up-5>.column:nth-of-type(1n),.large-up-5>.columns:nth-of-type(1n){clear:none}.large-up-5>.column:nth-of-type(5n+1),.large-up-5>.columns:nth-of-type(5n+1){clear:both}.large-up-5>.column:last-child,.large-up-5>.columns:last-child{float:left}.large-up-6>.column,.large-up-6>.columns{width:16.66667%;float:left}.large-up-6>.column:nth-of-type(1n),.large-up-6>.columns:nth-of-type(1n){clear:none}.large-up-6>.column:nth-of-type(6n+1),.large-up-6>.columns:nth-of-type(6n+1){clear:both}.large-up-6>.column:last-child,.large-up-6>.columns:last-child{float:left}.large-up-7>.column,.large-up-7>.columns{width:14.28571%;float:left}.large-up-7>.column:nth-of-type(1n),.large-up-7>.columns:nth-of-type(1n){clear:none}.large-up-7>.column:nth-of-type(7n+1),.large-up-7>.columns:nth-of-type(7n+1){clear:both}.large-up-7>.column:last-child,.large-up-7>.columns:last-child{float:left}.large-up-8>.column,.large-up-8>.columns{width:12.5%;float:left}.large-up-8>.column:nth-of-type(1n),.large-up-8>.columns:nth-of-type(1n){clear:none}.large-up-8>.column:nth-of-type(8n+1),.large-up-8>.columns:nth-of-type(8n+1){clear:both}.large-up-8>.column:last-child,.large-up-8>.columns:last-child{float:left}.large-collapse>.column,.large-collapse>.columns{padding-left:0;padding-right:0}.large-collapse .row{margin-left:0;margin-right:0}.expanded.row .large-collapse.row{margin-left:0;margin-right:0}.large-uncollapse>.column,.large-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem}.large-centered{margin-left:auto;margin-right:auto}.large-centered,.large-centered:last-child:not(:first-child){float:none;clear:both}.large-uncentered,.large-push-0,.large-pull-0{position:static;margin-left:0;margin-right:0;float:left}}.clearfix::before,.clearfix::after{content:' ';display:table}.clearfix::after{clear:both}html.js .no-js,html.js .hide-with-js{display:none}html.no-js .js,html.no-js .hide-with-nojs{display:none}.no-margin-bottom{margin-bottom:0 !important}.no-margin-top{margin-top:0 !important}.no-margin{margin:0 !important}.text-center{text-align:center}.text-right{text-align:right}.visuallyhidden{position:absolute;overflow:hidden;clip:rect(0 0 0 0);height:1px;width:1px;margin:-1px;padding:0;border:0}.show-on-focus{position:absolute !important;width:1px;height:1px;overflow:hidden;clip:rect(0, 0, 0, 0);color:#1f4a7f}.show-on-focus:active,.show-on-focus:focus{z-index:9999;position:static !important;height:auto;width:auto;overflow:visible;clip:auto}.show-on-focus:hover{color:#1f4a7f}.show-on-focus.skiplink:active,.show-on-focus.skiplink:focus{position:absolute !important;top:0;left:0;right:0;height:auto;text-align:center;line-height:1;padding:10px;background:#fff}.show-on-focus:hover{text-decoration:underline}form.docsearch label[for="tipue_search_input"]{position:absolute !important;clip:rect(1px 1px 1px 1px);clip:rect(1px, 1px, 1px, 1px);padding:0 !important;border:0 !important;height:1px !important;width:1px !important;overflow:hidden}body:hover form.docsearch label[for="tipue_search_input"] a,form.docsearch body:hover label[for="tipue_search_input"] a,body:hover form.docsearch label[for="tipue_search_input"] input,form.docsearch body:hover label[for="tipue_search_input"] input,body:hover form.docsearch label[for="tipue_search_input"] button,form.docsearch body:hover label[for="tipue_search_input"] button{display:none !important}.lazyload,.lazyloading{opacity:0}.lazyloaded{opacity:1;transition:opacity 0.3s ease-in-out}.no-js img.lazyload{display:none}form{margin:0}form .required{color:#d60202}form input,form textarea{font-size:100%}.button,.button.small,input[type="submit"]{background-size:1px 200%;transition:background-position 0.4s ease-in-out;border-radius:0;color:#fff;font-weight:700;padding:.625rem 1rem}.button:hover,.button.small:hover,input[type="submit"]:hover{background-position:100%}.button svg,.button.small svg,input[type="submit"] svg{fill:#fff;height:.75rem;width:1rem}.button.chevron-right,.button.small.chevron-right,input[type="submit"].chevron-right{margin:0 -.125rem 0 .125rem}.button.chevron-left,.button.small.chevron-left,input[type="submit"].chevron-left{margin:0 .125rem 0 -.125rem}.button.outline,.button.small.outline,input[type="submit"].outline{background-color:transparent;border:.0625rem solid}html,body{margin:0;padding:0;height:100%;background:#fafafa}body{visibility:visible;opacity:1;-webkit-font-smoothing:antialiased;font-size:100%}*{box-sizing:border-box}.browserupgrade{position:absolute;top:0;left:0;right:0;margin:0.2em 0;background:#ccc;color:#000;padding:0.2em 0;text-align:center}.pagewrapper{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;width:100%}@media screen and (min-width: 64em){.pagewrapper{position:absolute;top:0;left:0;height:100%}}.pagecontent{width:100%;box-sizing:content-box}@media screen and (max-width: 39.9375em){.pagecontent{-ms-flex-order:2;order:2}}@media screen and (min-width: 64em){.pagecontent{position:absolute;top:0;right:0;left:18.75rem;width:auto;left:auto;padding-top:3.5rem;padding-right:calc((100% - 64rem)/2);width:45.25rem}}.maincontent{padding:0 1.25rem}@media screen and (min-width: 64em){.maincontent{padding:0 1.875rem}}aside.sidebar{box-sizing:content-box}@media screen and (min-width: 64em){aside.sidebar{position:fixed;top:0;left:0;width:18.75rem;height:100%;padding-left:calc((100% - 64rem)/2)}}.editfooter p{font-size:80%}.pageheader{height:3.5625rem;display:-ms-flexbox;display:flex;-ms-flex-direction:row;flex-direction:row;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-ms-flex-pack:justify;justify-content:space-between;padding:0 1.875rem;color:#555;background:#fafafa;border-bottom:1px solid rgba(0,0,0,0.05)}.pageheader .headerlinks{display:none;-ms-flex-align:center;align-items:center;white-space:nowrap;font-size:.875rem}@media screen and (min-width: 64em){.pageheader .headerlinks{display:-ms-flexbox;display:flex}}@media screen and (min-width: 64em){.pageheader{position:absolute;top:0;left:0;right:0;padding:0 2.8125rem}}form.docsearch{position:relative;width:100%;margin:0;padding:0}form.docsearch input[type="search"]{display:block;width:100%;min-width:9.375rem;height:100%;padding:1.0625rem 1.0625rem 1.0625rem 1.875rem;border:3px solid #fafafa;transition:border-color .2s ease-in-out;background:#fafafa}form.docsearch input[type="search"]:focus{outline:none;border-color:#ff8f0d}form.docsearch .button{position:absolute;top:0;left:0;width:1.5rem;height:100%;padding:0;background:transparent;border:none;outline:none;color:#555}form.docsearch .button svg{fill:#555;height:100%;width:100%;max-height:1.5rem}.pagecontent{background-color:#fafafa}h1,h2,h3,h4,h5,h6{margin-top:1.5rem;margin-bottom:1rem;font-family:"Maven Pro",sans-serif;font-weight:600;line-height:1.4;text-rendering:optimizeLegibility;color:#1f4a7f}h1{font-size:1.75rem}h2{font-size:1.625rem}h3{font-size:1.5rem}h4{font-size:1.375rem}h5{font-size:1.25rem}h6{font-size:1.125rem}h1{margin-top:2.5rem}p,td,th{margin:0 0 1rem;font-size:.9375rem;line-height:1.6;text-rendering:optimizeLegibility}a{color:#1f4a7f;cursor:pointer;font-weight:700;text-decoration:none;transition:color .2s ease-in-out}a:hover{color:#ff8f0d}table{border:1px solid #ddd;border-radius:3px;border-spacing:0}table tr{border-collapse:collapse}table th{text-align:left;white-space:nowrap}table td,table th{padding:0.5em;border-bottom:1px solid #ddd;vertical-align:top}table th{border-bottom-width:2px}aside.sidebar{background:#1f4a7f;color:#fff;text-shadow:0 0 .9375rem rgba(0,0,0,0.15)}@media screen and (min-width: 64em){aside.sidebar{border-right:3px solid #132843}}.logo{display:block;margin:0;text-indent:100%;white-space:nowrap;overflow:hidden}.logo a{display:block;width:11rem;height:2.375rem;margin:.9375rem auto .9375rem 1.875rem;background:transparent url(https://assets.modmore.com/img/tpl/logo-modmore-20130403.png) no-repeat center center;background-size:100%}@media screen and (min-width: 64em){.logo a{width:12.5rem;height:2.8125rem;margin:2.1875rem auto 1.875rem .9375rem}}button.open-nav{z-index:999;display:block;background:#1f4a7f;padding:1.125rem 1.1875rem 1.25rem 1.3125rem;width:4.25rem;height:4.25rem;position:fixed;top:0;right:0;border:none;box-shadow:none;cursor:pointer;outline:none}@media screen and (min-width: 64em){button.open-nav{display:none}}button.open-nav .trigger-status{position:absolute;left:-99999px;width:1px;height:1px}button.open-nav span{color:#fff;text-transform:uppercase;font-size:.5625rem;display:block;margin-top:.0625rem}button.open-nav svg{fill:#fff}button.open-nav.active .menu{position:absolute;left:-99999px;width:1px;height:1px}button.open-nav.active .trigger-status{position:static;width:auto;height:auto}button.open-nav.active .line-1{-webkit-transform:rotate(45deg) translate(5px, -5px);transform:rotate(45deg) translate(5px, -5px)}button.open-nav.active .line-2{opacity:0}button.open-nav.active .line-3{-webkit-transform:rotate(-45deg) translate(-14px, -3px);transform:rotate(-45deg) translate(-14px, -3px)}nav.pagenav{display:none}nav.pagenav.active{display:block;position:fixed;top:0;left:0;right:0;width:100%;height:100vh;overflow-x:hidden;overflow-y:scroll;-webkit-overflow-scrolling:touch;background:#1f4a7f;padding:1.875rem}@media screen and (min-width: 64em){nav.pagenav{display:block}}nav.pagenav ul{display:block;margin:0;padding:0;list-style:none;font-size:1rem}nav.pagenav svg{fill:#fff;width:1.375rem;height:1.375rem;vertical-align:middle;position:relative;top:-2px;margin-right:2px}nav.pagenav>ul>li>a{padding-top:.5625rem;font-weight:700}nav.pagenav li{display:block;margin:0;padding:0}nav.pagenav a{display:block;padding:.375rem .9375rem;color:#fff}nav.pagenav a:hover{color:#ff8f0d}nav.pagenav>ul>li>ul>li>a{padding-left:2.8125rem;font-size:.75rem;text-transform:uppercase}nav.pagenav li li li a{padding-left:3.75rem;font-size:.75rem;font-weight:400}nav.pagenav li li li li a{padding-left:4.6875rem}nav.pagenav li li li li li a{padding-left:5.625rem}.Nav{margin:0;padding:0}.Nav__arrow{display:inline-block;position:relative;width:16px;margin-left:-16px}.Nav__arrow:before{position:absolute;display:block;content:"";margin:-.3em 0 0 -.4em;left:50%;top:50%;width:.5em;height:.5em;border-right:.15em solid #fff;border-top:.15em solid #fefefe;-webkit-transform:rotate(45deg);transform:rotate(45deg);transition-duration:.3s}.Nav__item{display:block}.Nav__item a{display:block}.Nav .Nav{display:none}nav.pagenav .Nav__item--active>a,nav.pagenav .Nav__item--open>a{font-weight:bold;color:#ff8f0d}.Nav__item--open>.Nav{display:block}.Nav__item--open>a>.Nav__arrow:before{-webkit-transform:rotate(135deg);transform:rotate(135deg);margin-top:-0.5em}.pagenav>.Nav>.Nav__item>a>.Nav__arrow{margin-left:-20px;width:16px;margin-right:4px}.Page__Header svg{width:0.4em}.Page__Header svg:last-of-type{display:none}.Page__Header a{font-size:70%}.Page__Header a:last-of-type{display:block;font-size:100%}.hljs{display:block;overflow-x:auto;padding:0.5em;background:#fdf6e3;color:#657b83}.hljs-comment,.hljs-quote{color:#93a1a1}.hljs-keyword,.hljs-selector-tag,.hljs-addition{color:#859900}.hljs-number,.hljs-string,.hljs-meta .hljs-meta-string,.hljs-literal,.hljs-doctag,.hljs-regexp{color:#2aa198}.hljs-title,.hljs-section,.hljs-name,.hljs-selector-id,.hljs-selector-class{color:#268bd2}.hljs-attribute,.hljs-attr,.hljs-variable,.hljs-template-variable,.hljs-class .hljs-title,.hljs-type{color:#b58900}.hljs-symbol,.hljs-bullet,.hljs-subst,.hljs-meta,.hljs-meta .hljs-keyword,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-link{color:#cb4b16}.hljs-built_in,.hljs-deletion{color:#dc322f}.hljs-formula{background:#eee8d5}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold}#tipue_search_warning{font-weight:300;font-size:15px;line-height:1.6;color:#555;margin:7px 0}#tipue_search_warning a{color:#396;text-decoration:none}#tipue_search_warning a:hover{color:#555}#tipue_search_results_count{font-weight:300;font-size:15px;line-height:1.7;color:#555}.tipue_search_content_title{font-weight:300;font-size:21px;line-height:1.7;margin-top:23px}.tipue_search_content_title a{color:#333;text-decoration:none}.tipue_search_content_title a:hover{color:#555}.tipue_search_content_url{font-weight:300;font-size:14px;line-height:1.9;word-wrap:break-word;-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto}.tipue_search_content_url a{color:#396;text-decoration:none}.tipue_search_content_url a:hover{color:#555}.tipue_search_content_text{font-weight:300;font-size:15px;line-height:1.6;color:#555;word-wrap:break-word;-webkit-hyphens:auto;-moz-hyphens:auto;-ms-hyphens:auto;hyphens:auto;margin-top:3px}.tipue_search_content_debug{font-weight:300;font-size:13px;line-height:1.6;color:#555;margin:5px 0}.h01{color:#333;font-weight:400}#tipue_search_foot{margin:51px 0 21px 0;padding:0 10px}#tipue_search_foot_boxes li{margin:0 4px}#tipue_search_foot_boxes li.current{display:inline-block;padding:5px 14px;border-radius:15px;color:#333;background:#f6f6f6;border:1px solid #e2e2e2}.tipue_search_spinner{padding:31px 0;width:50px;height:28px}.tipue_search_spinner>div{background-color:#777;height:100%;width:3px;display:inline-block;margin-right:2px;-webkit-animation:stretchdelay 1.2s infinite ease-in-out;animation:stretchdelay 1.2s infinite ease-in-out}.tipue_search_spinner .tipue_search_rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.tipue_search_spinner .tipue_search_rect3{-webkit-animation-delay:-1.0s;animation-delay:-1.0s}@-webkit-keyframes stretchdelay{0%,40%,100%{-webkit-transform:scaleY(0.4)}20%{-webkit-transform:scaleY(1)}}@keyframes stretchdelay{0%,40%,100%{transform:scaleY(0.4);-webkit-transform:scaleY(0.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}aside.sidebar{overflow-y:scroll}.s-content img,.s-content iframe,.s-content pre{max-width:100%}.s-content li{font-size:.875rem;line-height:1.6;text-rendering:optimizeLegibility}.s-content li>p:last-of-type{margin-bottom:0}.Pager{padding-left:0;margin:1em 0;list-style:none;text-align:center;clear:both}.Pager:after,.Pager:before{content:" ";display:table}.Pager:after{clear:both}.Pager li{display:inline}.Pager li>a{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px;transition:all .2s ease-in-out}.Pager li>a:focus,.Pager li>a:hover{text-decoration:none;border-color:#ff8f0d}.Pager--next>a{float:right}.Pager--prev>a{float:left} -/*# sourceMappingURL=main.css.map */ \ No newline at end of file +@-ms-viewport{width:device-width}/*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:rgba(0,0,0,0);-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,html [type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none}.row{max-width:44.25rem;margin-left:auto;margin-right:auto}.row::before,.row::after{content:" ";display:table}.row::after{clear:both}.row.collapse>.column,.row.collapse>.columns{padding-left:0;padding-right:0}.row .row{margin-left:-0.625rem;margin-right:-0.625rem}@media screen and (min-width: 40em){.row .row{margin-left:-0.9375rem;margin-right:-0.9375rem}}.row .row.collapse{margin-left:0;margin-right:0}.row.expanded{max-width:none}.row.expanded .row{margin-left:auto;margin-right:auto}.column,.columns{width:100%;float:left;padding-left:.625rem;padding-right:.625rem}@media screen and (min-width: 40em){.column,.columns{padding-left:.9375rem;padding-right:.9375rem}}.column:last-child:not(:first-child),.columns:last-child:not(:first-child){float:right}.column.end:last-child:last-child,.end.columns:last-child:last-child{float:left}.column.row.row,.row.row.columns{float:none}.row .column.row.row,.row .row.row.columns{padding-left:0;padding-right:0;margin-left:0;margin-right:0}.small-1{width:8.3333333333%}.small-push-1{position:relative;left:8.3333333333%}.small-pull-1{position:relative;left:-8.3333333333%}.small-offset-0{margin-left:0%}.small-2{width:16.6666666667%}.small-push-2{position:relative;left:16.6666666667%}.small-pull-2{position:relative;left:-16.6666666667%}.small-offset-1{margin-left:8.3333333333%}.small-3{width:25%}.small-push-3{position:relative;left:25%}.small-pull-3{position:relative;left:-25%}.small-offset-2{margin-left:16.6666666667%}.small-4{width:33.3333333333%}.small-push-4{position:relative;left:33.3333333333%}.small-pull-4{position:relative;left:-33.3333333333%}.small-offset-3{margin-left:25%}.small-5{width:41.6666666667%}.small-push-5{position:relative;left:41.6666666667%}.small-pull-5{position:relative;left:-41.6666666667%}.small-offset-4{margin-left:33.3333333333%}.small-6{width:50%}.small-push-6{position:relative;left:50%}.small-pull-6{position:relative;left:-50%}.small-offset-5{margin-left:41.6666666667%}.small-7{width:58.3333333333%}.small-push-7{position:relative;left:58.3333333333%}.small-pull-7{position:relative;left:-58.3333333333%}.small-offset-6{margin-left:50%}.small-8{width:66.6666666667%}.small-push-8{position:relative;left:66.6666666667%}.small-pull-8{position:relative;left:-66.6666666667%}.small-offset-7{margin-left:58.3333333333%}.small-9{width:75%}.small-push-9{position:relative;left:75%}.small-pull-9{position:relative;left:-75%}.small-offset-8{margin-left:66.6666666667%}.small-10{width:83.3333333333%}.small-push-10{position:relative;left:83.3333333333%}.small-pull-10{position:relative;left:-83.3333333333%}.small-offset-9{margin-left:75%}.small-11{width:91.6666666667%}.small-push-11{position:relative;left:91.6666666667%}.small-pull-11{position:relative;left:-91.6666666667%}.small-offset-10{margin-left:83.3333333333%}.small-12{width:100%}.small-offset-11{margin-left:91.6666666667%}.small-up-1>.column,.small-up-1>.columns{width:100%;float:left}.small-up-1>.column:nth-of-type(1n),.small-up-1>.columns:nth-of-type(1n){clear:none}.small-up-1>.column:nth-of-type(1n+1),.small-up-1>.columns:nth-of-type(1n+1){clear:both}.small-up-1>.column:last-child,.small-up-1>.columns:last-child{float:left}.small-up-2>.column,.small-up-2>.columns{width:50%;float:left}.small-up-2>.column:nth-of-type(1n),.small-up-2>.columns:nth-of-type(1n){clear:none}.small-up-2>.column:nth-of-type(2n+1),.small-up-2>.columns:nth-of-type(2n+1){clear:both}.small-up-2>.column:last-child,.small-up-2>.columns:last-child{float:left}.small-up-3>.column,.small-up-3>.columns{width:33.3333333333%;float:left}.small-up-3>.column:nth-of-type(1n),.small-up-3>.columns:nth-of-type(1n){clear:none}.small-up-3>.column:nth-of-type(3n+1),.small-up-3>.columns:nth-of-type(3n+1){clear:both}.small-up-3>.column:last-child,.small-up-3>.columns:last-child{float:left}.small-up-4>.column,.small-up-4>.columns{width:25%;float:left}.small-up-4>.column:nth-of-type(1n),.small-up-4>.columns:nth-of-type(1n){clear:none}.small-up-4>.column:nth-of-type(4n+1),.small-up-4>.columns:nth-of-type(4n+1){clear:both}.small-up-4>.column:last-child,.small-up-4>.columns:last-child{float:left}.small-up-5>.column,.small-up-5>.columns{width:20%;float:left}.small-up-5>.column:nth-of-type(1n),.small-up-5>.columns:nth-of-type(1n){clear:none}.small-up-5>.column:nth-of-type(5n+1),.small-up-5>.columns:nth-of-type(5n+1){clear:both}.small-up-5>.column:last-child,.small-up-5>.columns:last-child{float:left}.small-up-6>.column,.small-up-6>.columns{width:16.6666666667%;float:left}.small-up-6>.column:nth-of-type(1n),.small-up-6>.columns:nth-of-type(1n){clear:none}.small-up-6>.column:nth-of-type(6n+1),.small-up-6>.columns:nth-of-type(6n+1){clear:both}.small-up-6>.column:last-child,.small-up-6>.columns:last-child{float:left}.small-up-7>.column,.small-up-7>.columns{width:14.2857142857%;float:left}.small-up-7>.column:nth-of-type(1n),.small-up-7>.columns:nth-of-type(1n){clear:none}.small-up-7>.column:nth-of-type(7n+1),.small-up-7>.columns:nth-of-type(7n+1){clear:both}.small-up-7>.column:last-child,.small-up-7>.columns:last-child{float:left}.small-up-8>.column,.small-up-8>.columns{width:12.5%;float:left}.small-up-8>.column:nth-of-type(1n),.small-up-8>.columns:nth-of-type(1n){clear:none}.small-up-8>.column:nth-of-type(8n+1),.small-up-8>.columns:nth-of-type(8n+1){clear:both}.small-up-8>.column:last-child,.small-up-8>.columns:last-child{float:left}.small-collapse>.column,.small-collapse>.columns{padding-left:0;padding-right:0}.small-collapse .row{margin-left:0;margin-right:0}.expanded.row .small-collapse.row{margin-left:0;margin-right:0}.small-uncollapse>.column,.small-uncollapse>.columns{padding-left:.625rem;padding-right:.625rem}.small-centered{margin-left:auto;margin-right:auto}.small-centered,.small-centered:last-child:not(:first-child){float:none;clear:both}.small-uncentered,.small-push-0,.small-pull-0{position:static;margin-left:0;margin-right:0;float:left}@media screen and (min-width: 40em){.medium-1{width:8.3333333333%}.medium-push-1{position:relative;left:8.3333333333%}.medium-pull-1{position:relative;left:-8.3333333333%}.medium-offset-0{margin-left:0%}.medium-2{width:16.6666666667%}.medium-push-2{position:relative;left:16.6666666667%}.medium-pull-2{position:relative;left:-16.6666666667%}.medium-offset-1{margin-left:8.3333333333%}.medium-3{width:25%}.medium-push-3{position:relative;left:25%}.medium-pull-3{position:relative;left:-25%}.medium-offset-2{margin-left:16.6666666667%}.medium-4{width:33.3333333333%}.medium-push-4{position:relative;left:33.3333333333%}.medium-pull-4{position:relative;left:-33.3333333333%}.medium-offset-3{margin-left:25%}.medium-5{width:41.6666666667%}.medium-push-5{position:relative;left:41.6666666667%}.medium-pull-5{position:relative;left:-41.6666666667%}.medium-offset-4{margin-left:33.3333333333%}.medium-6{width:50%}.medium-push-6{position:relative;left:50%}.medium-pull-6{position:relative;left:-50%}.medium-offset-5{margin-left:41.6666666667%}.medium-7{width:58.3333333333%}.medium-push-7{position:relative;left:58.3333333333%}.medium-pull-7{position:relative;left:-58.3333333333%}.medium-offset-6{margin-left:50%}.medium-8{width:66.6666666667%}.medium-push-8{position:relative;left:66.6666666667%}.medium-pull-8{position:relative;left:-66.6666666667%}.medium-offset-7{margin-left:58.3333333333%}.medium-9{width:75%}.medium-push-9{position:relative;left:75%}.medium-pull-9{position:relative;left:-75%}.medium-offset-8{margin-left:66.6666666667%}.medium-10{width:83.3333333333%}.medium-push-10{position:relative;left:83.3333333333%}.medium-pull-10{position:relative;left:-83.3333333333%}.medium-offset-9{margin-left:75%}.medium-11{width:91.6666666667%}.medium-push-11{position:relative;left:91.6666666667%}.medium-pull-11{position:relative;left:-91.6666666667%}.medium-offset-10{margin-left:83.3333333333%}.medium-12{width:100%}.medium-offset-11{margin-left:91.6666666667%}.medium-up-1>.column,.medium-up-1>.columns{width:100%;float:left}.medium-up-1>.column:nth-of-type(1n),.medium-up-1>.columns:nth-of-type(1n){clear:none}.medium-up-1>.column:nth-of-type(1n+1),.medium-up-1>.columns:nth-of-type(1n+1){clear:both}.medium-up-1>.column:last-child,.medium-up-1>.columns:last-child{float:left}.medium-up-2>.column,.medium-up-2>.columns{width:50%;float:left}.medium-up-2>.column:nth-of-type(1n),.medium-up-2>.columns:nth-of-type(1n){clear:none}.medium-up-2>.column:nth-of-type(2n+1),.medium-up-2>.columns:nth-of-type(2n+1){clear:both}.medium-up-2>.column:last-child,.medium-up-2>.columns:last-child{float:left}.medium-up-3>.column,.medium-up-3>.columns{width:33.3333333333%;float:left}.medium-up-3>.column:nth-of-type(1n),.medium-up-3>.columns:nth-of-type(1n){clear:none}.medium-up-3>.column:nth-of-type(3n+1),.medium-up-3>.columns:nth-of-type(3n+1){clear:both}.medium-up-3>.column:last-child,.medium-up-3>.columns:last-child{float:left}.medium-up-4>.column,.medium-up-4>.columns{width:25%;float:left}.medium-up-4>.column:nth-of-type(1n),.medium-up-4>.columns:nth-of-type(1n){clear:none}.medium-up-4>.column:nth-of-type(4n+1),.medium-up-4>.columns:nth-of-type(4n+1){clear:both}.medium-up-4>.column:last-child,.medium-up-4>.columns:last-child{float:left}.medium-up-5>.column,.medium-up-5>.columns{width:20%;float:left}.medium-up-5>.column:nth-of-type(1n),.medium-up-5>.columns:nth-of-type(1n){clear:none}.medium-up-5>.column:nth-of-type(5n+1),.medium-up-5>.columns:nth-of-type(5n+1){clear:both}.medium-up-5>.column:last-child,.medium-up-5>.columns:last-child{float:left}.medium-up-6>.column,.medium-up-6>.columns{width:16.6666666667%;float:left}.medium-up-6>.column:nth-of-type(1n),.medium-up-6>.columns:nth-of-type(1n){clear:none}.medium-up-6>.column:nth-of-type(6n+1),.medium-up-6>.columns:nth-of-type(6n+1){clear:both}.medium-up-6>.column:last-child,.medium-up-6>.columns:last-child{float:left}.medium-up-7>.column,.medium-up-7>.columns{width:14.2857142857%;float:left}.medium-up-7>.column:nth-of-type(1n),.medium-up-7>.columns:nth-of-type(1n){clear:none}.medium-up-7>.column:nth-of-type(7n+1),.medium-up-7>.columns:nth-of-type(7n+1){clear:both}.medium-up-7>.column:last-child,.medium-up-7>.columns:last-child{float:left}.medium-up-8>.column,.medium-up-8>.columns{width:12.5%;float:left}.medium-up-8>.column:nth-of-type(1n),.medium-up-8>.columns:nth-of-type(1n){clear:none}.medium-up-8>.column:nth-of-type(8n+1),.medium-up-8>.columns:nth-of-type(8n+1){clear:both}.medium-up-8>.column:last-child,.medium-up-8>.columns:last-child{float:left}.medium-collapse>.column,.medium-collapse>.columns{padding-left:0;padding-right:0}.medium-collapse .row{margin-left:0;margin-right:0}.expanded.row .medium-collapse.row{margin-left:0;margin-right:0}.medium-uncollapse>.column,.medium-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem}.medium-centered{margin-left:auto;margin-right:auto}.medium-centered,.medium-centered:last-child:not(:first-child){float:none;clear:both}.medium-uncentered,.medium-push-0,.medium-pull-0{position:static;margin-left:0;margin-right:0;float:left}}@media screen and (min-width: 64em){.large-1{width:8.3333333333%}.large-push-1{position:relative;left:8.3333333333%}.large-pull-1{position:relative;left:-8.3333333333%}.large-offset-0{margin-left:0%}.large-2{width:16.6666666667%}.large-push-2{position:relative;left:16.6666666667%}.large-pull-2{position:relative;left:-16.6666666667%}.large-offset-1{margin-left:8.3333333333%}.large-3{width:25%}.large-push-3{position:relative;left:25%}.large-pull-3{position:relative;left:-25%}.large-offset-2{margin-left:16.6666666667%}.large-4{width:33.3333333333%}.large-push-4{position:relative;left:33.3333333333%}.large-pull-4{position:relative;left:-33.3333333333%}.large-offset-3{margin-left:25%}.large-5{width:41.6666666667%}.large-push-5{position:relative;left:41.6666666667%}.large-pull-5{position:relative;left:-41.6666666667%}.large-offset-4{margin-left:33.3333333333%}.large-6{width:50%}.large-push-6{position:relative;left:50%}.large-pull-6{position:relative;left:-50%}.large-offset-5{margin-left:41.6666666667%}.large-7{width:58.3333333333%}.large-push-7{position:relative;left:58.3333333333%}.large-pull-7{position:relative;left:-58.3333333333%}.large-offset-6{margin-left:50%}.large-8{width:66.6666666667%}.large-push-8{position:relative;left:66.6666666667%}.large-pull-8{position:relative;left:-66.6666666667%}.large-offset-7{margin-left:58.3333333333%}.large-9{width:75%}.large-push-9{position:relative;left:75%}.large-pull-9{position:relative;left:-75%}.large-offset-8{margin-left:66.6666666667%}.large-10{width:83.3333333333%}.large-push-10{position:relative;left:83.3333333333%}.large-pull-10{position:relative;left:-83.3333333333%}.large-offset-9{margin-left:75%}.large-11{width:91.6666666667%}.large-push-11{position:relative;left:91.6666666667%}.large-pull-11{position:relative;left:-91.6666666667%}.large-offset-10{margin-left:83.3333333333%}.large-12{width:100%}.large-offset-11{margin-left:91.6666666667%}.large-up-1>.column,.large-up-1>.columns{width:100%;float:left}.large-up-1>.column:nth-of-type(1n),.large-up-1>.columns:nth-of-type(1n){clear:none}.large-up-1>.column:nth-of-type(1n+1),.large-up-1>.columns:nth-of-type(1n+1){clear:both}.large-up-1>.column:last-child,.large-up-1>.columns:last-child{float:left}.large-up-2>.column,.large-up-2>.columns{width:50%;float:left}.large-up-2>.column:nth-of-type(1n),.large-up-2>.columns:nth-of-type(1n){clear:none}.large-up-2>.column:nth-of-type(2n+1),.large-up-2>.columns:nth-of-type(2n+1){clear:both}.large-up-2>.column:last-child,.large-up-2>.columns:last-child{float:left}.large-up-3>.column,.large-up-3>.columns{width:33.3333333333%;float:left}.large-up-3>.column:nth-of-type(1n),.large-up-3>.columns:nth-of-type(1n){clear:none}.large-up-3>.column:nth-of-type(3n+1),.large-up-3>.columns:nth-of-type(3n+1){clear:both}.large-up-3>.column:last-child,.large-up-3>.columns:last-child{float:left}.large-up-4>.column,.large-up-4>.columns{width:25%;float:left}.large-up-4>.column:nth-of-type(1n),.large-up-4>.columns:nth-of-type(1n){clear:none}.large-up-4>.column:nth-of-type(4n+1),.large-up-4>.columns:nth-of-type(4n+1){clear:both}.large-up-4>.column:last-child,.large-up-4>.columns:last-child{float:left}.large-up-5>.column,.large-up-5>.columns{width:20%;float:left}.large-up-5>.column:nth-of-type(1n),.large-up-5>.columns:nth-of-type(1n){clear:none}.large-up-5>.column:nth-of-type(5n+1),.large-up-5>.columns:nth-of-type(5n+1){clear:both}.large-up-5>.column:last-child,.large-up-5>.columns:last-child{float:left}.large-up-6>.column,.large-up-6>.columns{width:16.6666666667%;float:left}.large-up-6>.column:nth-of-type(1n),.large-up-6>.columns:nth-of-type(1n){clear:none}.large-up-6>.column:nth-of-type(6n+1),.large-up-6>.columns:nth-of-type(6n+1){clear:both}.large-up-6>.column:last-child,.large-up-6>.columns:last-child{float:left}.large-up-7>.column,.large-up-7>.columns{width:14.2857142857%;float:left}.large-up-7>.column:nth-of-type(1n),.large-up-7>.columns:nth-of-type(1n){clear:none}.large-up-7>.column:nth-of-type(7n+1),.large-up-7>.columns:nth-of-type(7n+1){clear:both}.large-up-7>.column:last-child,.large-up-7>.columns:last-child{float:left}.large-up-8>.column,.large-up-8>.columns{width:12.5%;float:left}.large-up-8>.column:nth-of-type(1n),.large-up-8>.columns:nth-of-type(1n){clear:none}.large-up-8>.column:nth-of-type(8n+1),.large-up-8>.columns:nth-of-type(8n+1){clear:both}.large-up-8>.column:last-child,.large-up-8>.columns:last-child{float:left}.large-collapse>.column,.large-collapse>.columns{padding-left:0;padding-right:0}.large-collapse .row{margin-left:0;margin-right:0}.expanded.row .large-collapse.row{margin-left:0;margin-right:0}.large-uncollapse>.column,.large-uncollapse>.columns{padding-left:.9375rem;padding-right:.9375rem}.large-centered{margin-left:auto;margin-right:auto}.large-centered,.large-centered:last-child:not(:first-child){float:none;clear:both}.large-uncentered,.large-push-0,.large-pull-0{position:static;margin-left:0;margin-right:0;float:left}}.clearfix::before,.clearfix::after{content:" ";display:table}.clearfix::after{clear:both}html.js .no-js,html.js .hide-with-js{display:none}html.no-js .js,html.no-js .hide-with-nojs{display:none}.no-margin-bottom{margin-bottom:0 !important}.no-margin-top{margin-top:0 !important}.no-margin{margin:0 !important}.text-center{text-align:center}.text-right{text-align:right}.visuallyhidden{position:absolute;overflow:hidden;clip:rect(0 0 0 0);height:1px;width:1px;margin:-1px;padding:0;border:0}.show-on-focus{position:absolute !important;width:1px;height:1px;overflow:hidden;clip:rect(0, 0, 0, 0);color:#1f4a7f}.show-on-focus:active,.show-on-focus:focus{z-index:9999;position:static !important;height:auto;width:auto;overflow:visible;clip:auto}.show-on-focus:hover{color:#1f4a7f}.show-on-focus.skiplink:active,.show-on-focus.skiplink:focus{position:absolute !important;top:0;left:0;right:0;height:auto;text-align:center;line-height:1;padding:10px;background:#fff}.show-on-focus:hover{text-decoration:underline}form.docsearch label[for=tipue_search_input]{position:absolute !important;clip:rect(1px 1px 1px 1px);clip:rect(1px, 1px, 1px, 1px);padding:0 !important;border:0 !important;height:1px !important;width:1px !important;overflow:hidden}body:hover form.docsearch label[for=tipue_search_input] a,form.docsearch body:hover label[for=tipue_search_input] a,body:hover form.docsearch label[for=tipue_search_input] input,form.docsearch body:hover label[for=tipue_search_input] input,body:hover form.docsearch label[for=tipue_search_input] button,form.docsearch body:hover label[for=tipue_search_input] button{display:none !important}.lazyload,.lazyloading{opacity:0}.lazyloaded{opacity:1;transition:opacity .3s ease-in-out}.no-js img.lazyload{display:none}form{margin:0}form .required{color:#d60202}form input,form textarea{font-size:100%}.button,.button.small,input[type=submit]{background-size:1px 200%;transition:background-position .4s ease-in-out;border-radius:0;color:#fff;font-weight:700;padding:.625rem 1rem}.button:hover,.button.small:hover,input[type=submit]:hover{background-position:100%}.button svg,.button.small svg,input[type=submit] svg{fill:#fff;height:.75rem;width:1rem}.button.chevron-right,.button.small.chevron-right,input[type=submit].chevron-right{margin:0 -0.125rem 0 .125rem}.button.chevron-left,.button.small.chevron-left,input[type=submit].chevron-left{margin:0 .125rem 0 -0.125rem}.button.outline,.button.small.outline,input[type=submit].outline{background-color:rgba(0,0,0,0);border:.0625rem solid}html,body{margin:0;padding:0;height:100%;background:#fafafa}body{visibility:visible;opacity:1;-webkit-font-smoothing:antialiased;font-size:100%;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif}*{box-sizing:border-box}.browserupgrade{position:absolute;top:0;left:0;right:0;margin:.2em 0;background:#ccc;color:#000;padding:.2em 0;text-align:center}.pagewrapper{display:flex;flex-direction:column;width:100%}@media screen and (min-width: 64em){.pagewrapper{position:absolute;top:0;left:0;height:100%}}.pagecontent{width:100%;box-sizing:content-box}@media screen and (max-width: 39.9375em){.pagecontent{order:2}}@media screen and (min-width: 64em){.pagecontent{position:absolute;top:0;right:0;left:21.875rem;width:auto;padding-top:3.5rem;padding-right:calc((100% - 80rem)/2)}}.maincontent{padding:0 1.25rem}@media screen and (min-width: 64em){.maincontent{padding:0 1.875rem}}aside.sidebar{box-sizing:content-box}@media screen and (min-width: 64em){aside.sidebar{position:fixed;top:0;left:0;width:18.75rem;height:100%;padding-left:3.125rem}}.editfooter p{font-size:80%}.pageheader{height:3.5625rem;display:flex;flex-direction:row;flex-wrap:nowrap;justify-content:space-between;padding:0 1.875rem 0 0;color:#555;background:#fff;border-bottom:1px solid rgba(0,0,0,.05)}.pageheader .headerlinks{display:none;align-items:center;white-space:nowrap;font-size:.875rem}@media screen and (min-width: 64em){.pageheader .headerlinks{display:flex}}@media screen and (min-width: 64em){.pageheader{position:absolute;top:0;left:0;right:0;padding:0 2.8125rem 0 0}}form.docsearch{position:relative;width:100%;margin:0;padding:0}form.docsearch input[type=search]{display:block;width:100%;min-width:9.375rem;height:100%;padding:1.0625rem 1.0625rem 1.0625rem 1.875rem;border:3px solid #fff;transition:border-color .2s ease-in-out;background:#fff}form.docsearch input[type=search]:focus{outline:none;border-color:#ff8f0d}form.docsearch .button{position:absolute;top:0;left:0;width:1.5rem;height:100%;padding:0;background:rgba(0,0,0,0);border:none;outline:none;color:#555}form.docsearch .button svg{fill:#555;height:100%;width:100%;max-height:1.5rem}.pagecontent{background-color:#fafafa}h1,h2,h3,h4,h5,h6{margin-top:1.5rem;margin-bottom:1rem;font-family:"Maven Pro",sans-serif;font-weight:600;line-height:1.4;text-rendering:optimizeLegibility;color:#1f4a7f}h1,h2{margin-top:2rem}h2{border-bottom:2px solid #d2e3ee}h3,h4,h5,h6{padding-left:1rem;margin-bottom:.5rem}h3.TableOfContentsContainer__title,h4.TableOfContentsContainer__title,h5.TableOfContentsContainer__title,h6.TableOfContentsContainer__title{padding-left:0}h1{font-size:1.75rem}h2{font-size:1.625rem}h3{font-size:1.5rem}h4{font-size:1.375rem}h5{font-size:1.25rem}h6{font-size:1.125rem}h1{margin-top:2.5rem}p,td,th{margin:0 0 1rem;font-size:1rem;line-height:1.6;text-rendering:optimizeLegibility}a{color:#1f4a7f;cursor:pointer;font-weight:700;text-decoration:none;transition:color .2s ease-in-out}a:hover{color:#ff8f0d}table{border:1px solid #ddd;border-radius:3px;border-spacing:0}table tr{border-collapse:collapse}table th{text-align:left;white-space:nowrap}table td,table th{padding:.5em;border-bottom:1px solid #ddd;vertical-align:top}table th{border-bottom-width:2px}code,kbd,samp{background:#fdf6e3;color:#365661;padding:.25em}blockquote{background:#f7fafc;padding:1em 1.2em .95em;border-radius:4px;border:1px solid #d2e3ee;border-left-width:5px;box-shadow:0 0 3px rgba(39,44,49,.02),0 5px 22px -6px rgba(39,44,49,.05);margin-left:0;margin-right:0}blockquote :last-child{margin-bottom:0}.alert{background:#f7fafc;padding:1em 1.2em .95em;border-radius:4px;border:1px solid #d2e3ee;box-shadow:0 0 3px rgba(39,44,49,.02),0 5px 22px -6px rgba(39,44,49,.05);margin-bottom:1em}.alert :last-child{margin-bottom:0}.Permalink{margin-left:-1em;width:1em;display:inline-block;text-align:center;text-decoration:none !important}aside.sidebar{background:#1f4a7f;color:#fff;text-shadow:0 0 .9375rem rgba(0,0,0,.15)}.logo{display:block;margin:0;text-indent:100%;white-space:nowrap;overflow:hidden}.logo a{display:block;width:11rem;height:2.375rem;margin:.9375rem auto .9375rem 1.875rem;background:rgba(0,0,0,0) url(https://assets.modmore.com/img/tpl/logo-modmore-20130403.png) no-repeat center center;background-size:100%}@media screen and (min-width: 64em){.logo a{width:12.5rem;height:2.8125rem;margin:2.1875rem auto 1.875rem .9375rem}}button.open-nav{z-index:999;display:block;background:#1f4a7f;padding:1.125rem 1.1875rem 1.25rem 1.3125rem;width:4.25rem;height:4.25rem;position:fixed;top:0;right:0;border:none;box-shadow:none;cursor:pointer;outline:none}@media screen and (min-width: 64em){button.open-nav{display:none}}button.open-nav .trigger-status{position:absolute;left:-99999px;width:1px;height:1px}button.open-nav span{color:#fff;text-transform:uppercase;font-size:.5625rem;display:block;margin-top:.0625rem}button.open-nav svg{fill:#fff}button.open-nav.active .menu{position:absolute;left:-99999px;width:1px;height:1px}button.open-nav.active .trigger-status{position:static;width:auto;height:auto}button.open-nav.active .line-1{transform:rotate(45deg) translate(5px, -5px)}button.open-nav.active .line-2{opacity:0}button.open-nav.active .line-3{transform:rotate(-45deg) translate(-14px, -3px)}nav.pagenav{display:none}nav.pagenav.active{display:block;position:fixed;top:0;left:0;right:0;width:100%;height:100vh;overflow-x:hidden;overflow-y:scroll;-webkit-overflow-scrolling:touch;background:#1f4a7f;padding:1.875rem}@media screen and (min-width: 64em){nav.pagenav{display:block}}nav.pagenav ul{display:block;margin:0;padding:0;list-style:none;font-size:1rem}nav.pagenav svg{fill:#fff;width:1.375rem;height:1.375rem;vertical-align:middle;position:relative;top:-2px;margin-right:2px}nav.pagenav>ul>li>a{padding-top:.5625rem;font-weight:700}nav.pagenav li{display:block;margin:0;padding:0}nav.pagenav a{display:block;padding:.375rem .9375rem;color:#fff}nav.pagenav a:hover{color:#ff8f0d}nav.pagenav>ul>li>ul>li>a{padding-left:1.875rem;font-size:.875rem}nav.pagenav li li li a{padding-left:2.8125rem;font-size:.875rem;font-weight:400}nav.pagenav li li li li a{padding-left:4.6875rem}nav.pagenav li li li li li a{padding-left:5.625rem}.Nav{margin:0;padding:0}.Nav__arrow{display:inline-block;position:relative;width:16px;margin-left:-16px}.Nav__arrow:before{position:absolute;display:block;content:"";margin:-0.3em 0 0 -0.4em;left:50%;top:50%;width:.5em;height:.5em;border-right:.15em solid #fff;border-top:.15em solid #fefefe;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-transition-duration:.3s;transition-duration:.3s}.Nav__item{display:block}.Nav__item a{display:block}.Nav .Nav{display:none}nav.pagenav .Nav__item--active>a,nav.pagenav .Nav__item--open>a{font-weight:bold;color:#ff8f0d}.Nav__item--open>.Nav{display:block}.Nav__item--open>a>.Nav__arrow:before{-webkit-transform:rotate(135deg);transform:rotate(135deg);margin-top:-0.5em}.pagenav>.Nav>.Nav__item>a>.Nav__arrow{margin-left:-20px;width:16px;margin-right:4px}.Page__Header svg{width:.4em}.Page__Header svg:last-of-type{display:none}.Page__Header a{font-size:70%}.Page__Header a:last-of-type{display:block;font-size:100%}.hljs{display:block;overflow-x:auto;padding:.5em;background:#fdf6e3;color:#657b83}.hljs-comment,.hljs-quote{color:#93a1a1}.hljs-keyword,.hljs-selector-tag,.hljs-addition{color:#859900}.hljs-number,.hljs-string,.hljs-meta .hljs-meta-string,.hljs-literal,.hljs-doctag,.hljs-regexp{color:#2aa198}.hljs-title,.hljs-section,.hljs-name,.hljs-selector-id,.hljs-selector-class{color:#268bd2}.hljs-attribute,.hljs-attr,.hljs-variable,.hljs-template-variable,.hljs-class .hljs-title,.hljs-type{color:#b58900}.hljs-symbol,.hljs-bullet,.hljs-subst,.hljs-meta,.hljs-meta .hljs-keyword,.hljs-selector-attr,.hljs-selector-pseudo,.hljs-link{color:#cb4b16}.hljs-built_in,.hljs-deletion{color:#dc322f}.hljs-formula{background:#eee8d5}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:bold}.Search{position:relative;width:100%}.Search__field{display:block;width:100%;height:55px;padding:12px 30px 6px 50px;border-width:0 0 1px;border-bottom:1px solid var(--search-field-border-color);transition:border-color ease-in-out .15s}.Search__field:focus{border-color:var(--search-field-hover-border-color);outline:0}.Search__icon{position:absolute;left:20px;top:20px;width:18px;height:18px;cursor:pointer}.Navbar .Search{float:right;margin:8px 20px}.Navbar .Search__field{box-shadow:inset 0 1px 1px rgba(0,0,0,.075);border-width:0;border-radius:4px;padding-left:10px}.SearchResults .Search__field{height:1em;background:#f7fafc;padding:1em;border-radius:4px;border:1px solid #d2e3ee;box-shadow:0 0 3px rgba(39,44,49,.02),0 5px 22px -6px rgba(39,44,49,.05)}.SearchResults__close{line-height:1em;margin-right:.25em}.SearchResults__count{margin-top:.25em}aside.sidebar{overflow-y:scroll}.s-content img,.s-content iframe,.s-content pre{max-width:100%}.s-content li{font-size:1em;line-height:1.6;text-rendering:optimizeLegibility;margin-bottom:.4em}.s-content li>p:last-of-type{margin-bottom:0}.Pager{padding-left:0;margin:1em 0;list-style:none;text-align:center;clear:both}.Pager:after,.Pager:before{content:" ";display:table}.Pager:after{clear:both}.Pager li{display:inline}.Pager li>a{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px;transition:all .2s ease-in-out}.Pager li>a:focus,.Pager li>a:hover{text-decoration:none;border-color:#ff8f0d}.Pager--next>a{float:right}.Pager--prev>a{float:left}.u-visuallyHidden{position:absolute !important;height:1px;width:1px;overflow:hidden;clip:rect(1px 1px 1px 1px);clip:rect(1px, 1px, 1px, 1px);white-space:nowrap}.s-content a{font-weight:600;text-decoration:underline}.s-content a.Link--external{white-space:nowrap}.s-content a.Link--external:after{content:" " url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAVklEQVR4Xn3PgQkAMQhDUXfqTu7kTtkpd5RA8AInfArtQ2iRXFWT2QedAfttj2FsPIOE1eCOlEuoWWjgzYaB/IkeGOrxXhqB+uA9Bfcm0lAZuh+YIeAD+cAqSz4kCMUAAAAASUVORK5CYII=)}.s-content a.Link--broken{color:red}.s-content table{min-width:100%;margin-bottom:1em}@media screen and (min-width: 64em){.s-content table{margin-left:-2.5em;margin-right:-2.5em}}/*# sourceMappingURL=main.css.map */ diff --git a/themes/modmore/dist/main.css.map b/themes/modmore/dist/main.css.map index ab2c1668..d4720b52 100644 --- a/themes/modmore/dist/main.css.map +++ b/themes/modmore/dist/main.css.map @@ -1,91 +1 @@ -{ - "version": 3, - "file": "main.css", - "sources": [ - "../../../src/scss/main.scss", - "../../../src/bower_components/normalize.css/_normalize.scss", - "../../../src/bower_components/foundation-sites/scss/util/_util.scss", - "../../../src/bower_components/foundation-sites/scss/util/_unit.scss", - "../../../src/bower_components/foundation-sites/scss/util/_value.scss", - "../../../src/bower_components/foundation-sites/scss/util/_color.scss", - "../../../src/bower_components/foundation-sites/scss/util/_selector.scss", - "../../../src/bower_components/foundation-sites/scss/util/_flex.scss", - "../../../src/bower_components/foundation-sites/scss/util/_breakpoint.scss", - "../../../src/bower_components/foundation-sites/scss/util/_mixins.scss", - "../../../src/scss/_settings.scss", - "../../../src/scss/_functions.scss", - "../../../src/bower_components/foundation-sites/scss/foundation.scss", - "../../../src/bower_components/foundation-sites/scss/_global.scss", - "../../../src/bower_components/foundation-sites/scss/grid/_grid.scss", - "../../../src/bower_components/foundation-sites/scss/grid/_row.scss", - "../../../src/bower_components/foundation-sites/scss/grid/_column.scss", - "../../../src/bower_components/foundation-sites/scss/grid/_size.scss", - "../../../src/bower_components/foundation-sites/scss/grid/_position.scss", - "../../../src/bower_components/foundation-sites/scss/grid/_gutter.scss", - "../../../src/bower_components/foundation-sites/scss/grid/_classes.scss", - "../../../src/bower_components/foundation-sites/scss/grid/_layout.scss", - "../../../src/bower_components/foundation-sites/scss/grid/_flex-grid.scss", - "../../../src/bower_components/foundation-sites/scss/typography/_typography.scss", - "../../../src/bower_components/foundation-sites/scss/typography/_base.scss", - "../../../src/bower_components/foundation-sites/scss/typography/_helpers.scss", - "../../../src/bower_components/foundation-sites/scss/typography/_alignment.scss", - "../../../src/bower_components/foundation-sites/scss/typography/_print.scss", - "../../../src/bower_components/foundation-sites/scss/forms/_forms.scss", - "../../../src/bower_components/foundation-sites/scss/forms/_text.scss", - "../../../src/bower_components/foundation-sites/scss/forms/_checkbox.scss", - "../../../src/bower_components/foundation-sites/scss/forms/_label.scss", - "../../../src/bower_components/foundation-sites/scss/forms/_help-text.scss", - "../../../src/bower_components/foundation-sites/scss/forms/_input-group.scss", - "../../../src/bower_components/foundation-sites/scss/forms/_fieldset.scss", - "../../../src/bower_components/foundation-sites/scss/forms/_select.scss", - "../../../src/bower_components/foundation-sites/scss/forms/_range.scss", - "../../../src/bower_components/foundation-sites/scss/forms/_progress.scss", - "../../../src/bower_components/foundation-sites/scss/forms/_meter.scss", - "../../../src/bower_components/foundation-sites/scss/forms/_error.scss", - "../../../src/bower_components/foundation-sites/scss/components/_visibility.scss", - "../../../src/bower_components/foundation-sites/scss/components/_float.scss", - "../../../src/bower_components/foundation-sites/scss/components/_button.scss", - "../../../src/bower_components/foundation-sites/scss/components/_button-group.scss", - "../../../src/bower_components/foundation-sites/scss/components/_accordion-menu.scss", - "../../../src/bower_components/foundation-sites/scss/components/_accordion.scss", - "../../../src/bower_components/foundation-sites/scss/components/_badge.scss", - "../../../src/bower_components/foundation-sites/scss/components/_breadcrumbs.scss", - "../../../src/bower_components/foundation-sites/scss/components/_callout.scss", - "../../../src/bower_components/foundation-sites/scss/components/_close-button.scss", - "../../../src/bower_components/foundation-sites/scss/components/_drilldown.scss", - "../../../src/bower_components/foundation-sites/scss/components/_dropdown-menu.scss", - "../../../src/bower_components/foundation-sites/scss/components/_dropdown.scss", - "../../../src/bower_components/foundation-sites/scss/components/_flex.scss", - "../../../src/bower_components/foundation-sites/scss/components/_flex-video.scss", - "../../../src/bower_components/foundation-sites/scss/components/_label.scss", - "../../../src/bower_components/foundation-sites/scss/components/_media-object.scss", - "../../../src/bower_components/foundation-sites/scss/components/_menu.scss", - "../../../src/bower_components/foundation-sites/scss/components/_menu-icon.scss", - "../../../src/bower_components/foundation-sites/scss/components/_off-canvas.scss", - "../../../src/bower_components/foundation-sites/scss/components/_orbit.scss", - "../../../src/bower_components/foundation-sites/scss/components/_pagination.scss", - "../../../src/bower_components/foundation-sites/scss/components/_progress-bar.scss", - "../../../src/bower_components/foundation-sites/scss/components/_reveal.scss", - "../../../src/bower_components/foundation-sites/scss/components/_slider.scss", - "../../../src/bower_components/foundation-sites/scss/components/_sticky.scss", - "../../../src/bower_components/foundation-sites/scss/components/_switch.scss", - "../../../src/bower_components/foundation-sites/scss/components/_table.scss", - "../../../src/bower_components/foundation-sites/scss/components/_tabs.scss", - "../../../src/bower_components/foundation-sites/scss/components/_title-bar.scss", - "../../../src/bower_components/foundation-sites/scss/components/_top-bar.scss", - "../../../src/bower_components/foundation-sites/scss/components/_thumbnail.scss", - "../../../src/bower_components/foundation-sites/scss/components/_tooltip.scss", - "../../../src/scss/_helpers.scss", - "../../../src/scss/_lazyload.scss", - "../../../src/scss/_forms.scss", - "../../../src/scss/_template.scss", - "../../../src/scss/_pageheader.scss", - "../../../src/scss/_pagecontent.scss", - "../../../src/scss/_sidebar.scss", - "../../../src/scss/_daux.scss", - "../../../src/scss/_highlight.scss", - "../../../src/scss/_tipuesearch.scss" - ], - "mappings": "AAEA,aAAa,CACT,KAAK,CAAE,YAAa,CCHxB,4EAA4E,AAY5E,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,UAAW,CACxB,WAAW,CAAE,IAAK,CAClB,oBAAoB,CAAE,IAAK,CAC3B,wBAAwB,CAAE,IAAK,CAChC,AASD,AAAA,IAAI,AAAC,CACH,MAAM,CAAE,CAAE,CACX,AAMD,AAAA,OAAO,CACP,AAAA,KAAK,CACL,AAAA,MAAM,CACN,AAAA,MAAM,CACN,AAAA,GAAG,CACH,AAAA,OAAO,AAAC,CACN,OAAO,CAAE,KAAM,CAChB,AAOD,AAAA,EAAE,AAAC,CACD,SAAS,CAAE,GAAI,CACf,MAAM,CAAE,QAAS,CAClB,AAUD,AAAA,UAAU,CACV,AAAA,MAAM,CACN,AAAA,IAAI,AAAC,CACH,OAAO,CAAE,KAAM,CAChB,AAMD,AAAA,MAAM,AAAC,CACL,MAAM,CAAE,QAAS,CAClB,AAOD,AAAA,EAAE,AAAC,CACD,UAAU,CAAE,WAAY,CACxB,MAAM,CAAE,CAAE,CACV,QAAQ,CAAE,OAAQ,CACnB,AAOD,AAAA,GAAG,AAAC,CACF,WAAW,CAAE,oBAAqB,CAClC,SAAS,CAAE,GAAI,CAChB,AAUD,AAAA,CAAC,AAAC,CACA,gBAAgB,CAAE,WAAY,CAC9B,4BAA4B,CAAE,OAAQ,CACvC,AAOD,AAAC,CAAA,AAAA,OAAO,CACR,AAAC,CAAA,AAAA,MAAM,AAAC,CACN,aAAa,CAAE,CAAE,CAClB,AAOD,AAAU,IAAN,CAAA,AAAA,KAAC,AAAA,CAAO,CACV,aAAa,CAAE,IAAK,CACpB,eAAe,CAAE,SAAU,CAC3B,eAAe,CAAE,gBAAiB,CACnC,AAMD,AAAA,CAAC,CACD,AAAA,MAAM,AAAC,CACL,WAAW,CAAE,OAAQ,CACtB,AAMD,AAAA,CAAC,CACD,AAAA,MAAM,AAAC,CACL,WAAW,CAAE,MAAO,CACrB,AAOD,AAAA,IAAI,CACJ,AAAA,GAAG,CACH,AAAA,IAAI,AAAC,CACH,WAAW,CAAE,oBAAqB,CAClC,SAAS,CAAE,GAAI,CAChB,AAMD,AAAA,GAAG,AAAC,CACF,UAAU,CAAE,MAAO,CACpB,AAMD,AAAA,IAAI,AAAC,CACH,gBAAgB,CAAE,IAAK,CACvB,KAAK,CAAE,IAAK,CACb,AAMD,AAAA,KAAK,AAAC,CACJ,SAAS,CAAE,GAAI,CAChB,AAOD,AAAA,GAAG,CACH,AAAA,GAAG,AAAC,CACF,SAAS,CAAE,GAAI,CACf,WAAW,CAAE,CAAE,CACf,QAAQ,CAAE,QAAS,CACnB,cAAc,CAAE,QAAS,CAC1B,AAED,AAAA,GAAG,AAAC,CACF,MAAM,CAAE,OAAQ,CACjB,AAED,AAAA,GAAG,AAAC,CACF,GAAG,CAAE,MAAO,CACb,AASD,AAAA,KAAK,CACL,AAAA,KAAK,AAAC,CACJ,OAAO,CAAE,YAAa,CACvB,AAMD,AAAoB,KAAf,AAAA,IAAK,EAAA,AAAA,AAAS,QAAR,AAAA,EAAW,CACpB,OAAO,CAAE,IAAK,CACd,MAAM,CAAE,CAAE,CACX,AAMD,AAAA,GAAG,AAAC,CACF,YAAY,CAAE,IAAK,CACpB,AAMD,AAAa,GAAV,AAAA,IAAK,CAAA,AAAA,KAAK,CAAE,CACb,QAAQ,CAAE,MAAO,CAClB,AAUD,AAAA,MAAM,CACN,AAAA,KAAK,CACL,AAAA,QAAQ,CACR,AAAA,MAAM,CACN,AAAA,QAAQ,AAAC,CACP,WAAW,CAAE,UAAW,CACxB,SAAS,CAAE,IAAK,CAChB,WAAW,CAAE,IAAK,CAClB,MAAM,CAAE,CAAE,CACX,AAOD,AAAA,MAAM,CACN,AAAA,KAAK,AAAC,CACJ,QAAQ,CAAE,OAAQ,CACnB,AAOD,AAAA,MAAM,CACN,AAAA,MAAM,AAAC,CACL,cAAc,CAAE,IAAK,CACtB,AAQD,AAAA,MAAM,CACN,AAAmB,IAAf,EAAC,AAAA,IAAC,CAAK,QAAQ,AAAb,GACN,AAAA,AAAa,IAAZ,CAAK,OAAO,AAAZ,GACD,AAAA,AAAc,IAAb,CAAK,QAAQ,AAAb,CAAe,CACd,kBAAkB,CAAE,MAAO,CAC5B,AAMD,AAAM,MAAA,AAAA,kBAAkB,EACxB,AAAA,AAAe,IAAd,CAAK,QAAQ,AAAb,CAAc,kBAAkB,EACjC,AAAA,AAAc,IAAb,CAAK,OAAO,AAAZ,CAAa,kBAAkB,EAChC,AAAA,AAAe,IAAd,CAAK,QAAQ,AAAb,CAAc,kBAAkB,AAAC,CAChC,YAAY,CAAE,IAAK,CACnB,OAAO,CAAE,CAAE,CACZ,AAMD,AAAM,MAAA,AAAA,eAAe,EACrB,AAAA,AAAe,IAAd,CAAK,QAAQ,AAAb,CAAc,eAAe,EAC9B,AAAA,AAAc,IAAb,CAAK,OAAO,AAAZ,CAAa,eAAe,EAC7B,AAAA,AAAe,IAAd,CAAK,QAAQ,AAAb,CAAc,eAAe,AAAC,CAC7B,OAAO,CAAE,qBAAsB,CAChC,AAMD,AAAA,QAAQ,AAAC,CACP,MAAM,CAAE,iBAAkB,CAC1B,MAAM,CAAE,KAAM,CACd,OAAO,CAAE,qBAAsB,CAChC,AASD,AAAA,MAAM,AAAC,CACL,UAAU,CAAE,UAAW,CACvB,KAAK,CAAE,OAAQ,CACf,OAAO,CAAE,KAAM,CACf,SAAS,CAAE,IAAK,CAChB,OAAO,CAAE,CAAE,CACX,WAAW,CAAE,MAAO,CACrB,AAOD,AAAA,QAAQ,AAAC,CACP,OAAO,CAAE,YAAa,CACtB,cAAc,CAAE,QAAS,CAC1B,AAMD,AAAA,QAAQ,AAAC,CACP,QAAQ,CAAE,IAAK,CAChB,CAOD,AAAA,AAAgB,IAAf,CAAK,UAAU,AAAf,GACD,AAAA,AAAa,IAAZ,CAAK,OAAO,AAAZ,CAAc,CACb,UAAU,CAAE,UAAW,CACvB,OAAO,CAAE,CAAE,CACZ,CAMD,AAAA,AAAe,IAAd,CAAK,QAAQ,AAAb,CAAc,2BAA2B,EAC1C,AAAA,AAAe,IAAd,CAAK,QAAQ,AAAb,CAAc,2BAA2B,AAAC,CACzC,MAAM,CAAE,IAAK,CACd,CAOD,AAAA,AAAc,IAAb,CAAK,QAAQ,AAAb,CAAe,CACd,kBAAkB,CAAE,SAAU,CAC9B,cAAc,CAAE,IAAK,CACtB,CAMD,AAAA,AAAe,IAAd,CAAK,QAAQ,AAAb,CAAc,8BAA8B,EAC7C,AAAA,AAAe,IAAd,CAAK,QAAQ,AAAb,CAAc,2BAA2B,AAAC,CACzC,kBAAkB,CAAE,IAAK,CAC1B,AAOD,AAAA,4BAA4B,AAAC,CAC3B,kBAAkB,CAAE,MAAO,CAC3B,IAAI,CAAE,OAAQ,CACf,AAUD,AAAA,OAAO,CACP,AAAA,IAAI,AAAC,CACH,OAAO,CAAE,KAAM,CAChB,AAMD,AAAA,OAAO,AAAC,CACN,OAAO,CAAE,SAAU,CACpB,AASD,AAAA,MAAM,AAAC,CACL,OAAO,CAAE,YAAa,CACvB,AAMD,AAAA,QAAQ,AAAC,CACP,OAAO,CAAE,IAAK,CACf,CASD,AAAA,AAAO,MAAN,AAAA,CAAQ,CACP,OAAO,CAAE,IAAK,CACf,AmBnbC,AAAA,IAAI,AAAJ,CLoCE,SAAS,CZwBD,OAAU,CYvBlB,WAAW,CAAE,IAAK,CAClB,YAAY,CAAE,IAAK,CKTpB,AA7BD,AAAA,IAAI,AXoHH,QAAQ,CWpHT,AAAA,IAAI,AXqHH,OAAO,AAAC,CACP,OAAO,CAAE,GAAI,CACb,OAAO,CAAE,KAAM,CAKhB,AW5HD,AAAA,IAAI,AX8HH,OAAO,AAAC,CACP,KAAK,CAAE,IAAK,CACb,AWhID,AAKM,IALF,AAID,SAAS,CACN,OAAO,CALb,AAKI,IALA,AAID,SAAS,CAsHV,QAAQ,AArHN,CDpBJ,YAAY,CAAE,CAAE,CAChB,aAAa,CAAE,CAAE,CCqBZ,AAPL,AAWI,IAXA,CAWA,IAAI,AAAN,CLqDE,WAAW,CAHJ,QAAQ,CAIf,YAAY,CAJL,QAAQ,CK3ChB,AZwGD,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,IAAI,EY1H7B,AAWI,IAXA,CAWA,IAAI,AAAN,CLqDE,WAAW,CAHJ,SAAQ,CAIf,YAAY,CAJL,SAAQ,CK3ChB,CAlBH,AAWI,IAXA,CAWA,IAAI,AAGH,SAAS,AAAV,CACE,WAAW,CAAE,CAAE,CACf,YAAY,CAAE,CAAE,CACjB,AAjBL,AAAA,IAAI,AAqBD,SAAS,AAAV,CACE,SAAS,CAAE,IAAK,CAMjB,AA5BH,AAwBI,IAxBA,AAqBD,SAAS,CAGR,IAAI,AAAJ,CACE,WAAW,CAAE,IAAK,CAClB,YAAY,CAAE,IAAK,CACpB,AAKL,AAAA,OAAO,CA0FL,AA1FF,QA0FU,AA1FV,CH3CA,KAAK,CDeO,IAAU,CA+BtB,KAAK,CHyCgD,IAAI,CGjCnD,YAAY,CAHJ,OAAQ,CAIhB,aAAa,CAJL,OAAQ,CIArB,AZkFC,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,IAAI,EY1F7B,AAAA,OAAO,CA0FL,AA1FF,QA0FU,AA1FV,CJWM,YAAY,CAHJ,QAAQ,CAIhB,aAAa,CAJL,QAAQ,CIArB,CARD,AAAA,OAAO,AJwBJ,WAAW,AAAA,IAAK,CAAA,AAAA,YAAY,EIkE7B,AA1FF,QA0FU,AJlEP,WAAW,AAAA,IAAK,CAAA,AAAA,YAAY,CAAE,CAC7B,KAAK,CHoB4C,KAAK,CGnBvD,AI1BH,AAAA,OAAO,AAIF,IAAI,AFbR,WAAW,AAAA,WAAW,CEalB,AAJL,IAIS,AAsFP,QAAQ,AFnGT,WAAW,AAAA,WAAW,AAAC,CACtB,KAAK,CLoD8C,IAAI,CKnDxD,AEmBD,AAAW,OAAJ,AAAA,IAAI,AAAA,IAAI,CAAR,AAAP,IAAW,AAAA,IAAI,AA8Eb,QAAQ,AA9EV,CACE,KAAK,CAAE,IAAK,CACb,AAGD,AAAgB,IAAZ,CAAC,OAAO,AAAA,IAAI,AAAA,IAAI,CAApB,AAAA,IAAI,CAAQ,IAAI,AAAA,IAAI,AAyElB,QAAQ,AAzEV,CACE,YAAY,CAAE,CAAE,CAChB,aAAa,CAAE,CAAE,CACjB,WAAW,CAAE,CAAE,CACf,YAAY,CAAE,CAAE,CACjB,AAKG,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,QAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,QAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFhBV,EAAU,CI8EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,QAAU,CI2EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,GAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,GAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,IAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,GAAU,CI2EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,GAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,GAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,IAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,GAAU,CI2EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,GAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,GAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,IAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,cAAc,AAAd,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,cAAc,AAAd,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,GAAU,CI2EjB,AApBD,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,cAAc,AAAd,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,cAAc,AAAd,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,gBAAgB,AAAhB,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,IAAU,CIyDjB,AAgBD,AAAA,gBAAgB,AAAhB,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AAKD,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,IAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,GAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,SAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,GAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,GAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,SAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,SAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,KAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,AD4DD,AACI,eADW,CACX,OAAO,CADX,AACE,eADa,CAgCf,QAAQ,AA/BN,CD1GJ,YAAY,CAAE,CAAE,CAChB,aAAa,CAAE,CAAE,CCyGmB,AADlC,AAGE,eAHa,CAGb,IAAI,AAAJ,CACE,WAAW,CAAE,CAAE,CACf,YAAY,CAAE,CAAE,CACjB,AAGH,AAA6B,SAApB,AAAA,IAAI,CAAC,eAAe,AAAA,IAAI,AAAjC,CACE,WAAW,CAAE,CAAE,CACf,YAAY,CAAE,CAAE,CACjB,AAED,AAGI,iBAHa,CAGb,OAAO,CAHX,AAGE,iBAHe,CAkBjB,QAAQ,AAfN,CDjHJ,YAAY,CADH,OAAQ,CAEjB,aAAa,CAFJ,OAAQ,CCkH8B,AAI7C,AAAA,eAAe,AAAf,CFjHA,WAAW,CAAE,IAAK,CAClB,YAAY,CAAE,IAAK,CEkHlB,AAFD,AAAA,eAAe,CAAf,AAAA,eAAe,AFrHX,WAAW,AAAA,IAAK,CAAA,AAAA,YAAY,CAAE,CAChC,KAAK,CAAE,IAAK,CACZ,KAAK,CAAE,IAAK,CACb,AEuHD,AAAA,iBAAiB,CACjB,AAAA,aAAa,CACb,AAAA,aAAa,AAFb,CF5GF,QAAQ,CAAE,MAAO,CACjB,WAAW,CAAE,CAAE,CACf,YAAY,CAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CE2GT,AZID,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,IAAI,EY/DzB,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,QAAU,CIyDjB,AAIC,AAAA,cAAc,AAAd,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,QAAU,CE+Ed,AAED,AAAA,cAAc,AAAd,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CEmFd,AAMH,AAAA,gBAAgB,AAAhB,CF5DJ,WAAsB,CFhBV,EAAU,CI8EjB,AApBD,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,cAAc,AAAd,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,cAAc,AAAd,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,gBAAgB,AAAhB,CF5DJ,WAAsB,CFbV,QAAU,CI2EjB,AApBD,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,GAAU,CIyDjB,AAIC,AAAA,cAAc,AAAd,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,GAAU,CE+Ed,AAED,AAAA,cAAc,AAAd,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,IAAU,CEmFd,AAMH,AAAA,gBAAgB,AAAhB,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,cAAc,AAAd,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,cAAc,AAAd,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,gBAAgB,AAAhB,CF5DJ,WAAsB,CFbV,GAAU,CI2EjB,AApBD,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,cAAc,AAAd,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,cAAc,AAAd,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,gBAAgB,AAAhB,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,GAAU,CIyDjB,AAIC,AAAA,cAAc,AAAd,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,GAAU,CE+Ed,AAED,AAAA,cAAc,AAAd,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,IAAU,CEmFd,AAMH,AAAA,gBAAgB,AAAhB,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,cAAc,AAAd,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,cAAc,AAAd,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,gBAAgB,AAAhB,CF5DJ,WAAsB,CFbV,GAAU,CI2EjB,AApBD,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,cAAc,AAAd,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,cAAc,AAAd,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,gBAAgB,AAAhB,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,GAAU,CIyDjB,AAIC,AAAA,cAAc,AAAd,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,GAAU,CE+Ed,AAED,AAAA,cAAc,AAAd,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,IAAU,CEmFd,AAMH,AAAA,gBAAgB,AAAhB,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,UAAU,AAAV,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,eAAe,AAAf,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,eAAe,AAAf,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,gBAAgB,AAAhB,CF5DJ,WAAsB,CFbV,GAAU,CI2EjB,AApBD,AAAA,UAAU,AAAV,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,eAAe,AAAf,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,eAAe,AAAf,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,iBAAiB,AAAjB,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,UAAU,AAAV,CHtEJ,KAAK,CDeO,IAAU,CIyDjB,AAgBD,AAAA,iBAAiB,AAAjB,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AAKD,ACxFA,YDwFY,CCxFZ,OAAO,CDwFP,ACxFF,YDwFc,CAsCd,QAAQ,AC9HV,CACE,KAAK,CAAE,IAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,YDwFY,CCxFZ,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,YDwFc,CAsCd,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,YDwFY,CCxFZ,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,YDwFc,CAsCd,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,YDwFY,CCxFZ,OAAO,AAgCR,WAAW,CDwDV,ACxFF,YDwFc,CAsCd,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,YDwFY,CCxFZ,OAAO,CDwFP,ACxFF,YDwFc,CAsCd,QAAQ,AC9HV,CACE,KAAK,CAAE,GAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,YDwFY,CCxFZ,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,YDwFc,CAsCd,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,YDwFY,CCxFZ,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,YDwFc,CAsCd,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,YDwFY,CCxFZ,OAAO,AAgCR,WAAW,CDwDV,ACxFF,YDwFc,CAsCd,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,YDwFY,CCxFZ,OAAO,CDwFP,ACxFF,YDwFc,CAsCd,QAAQ,AC9HV,CACE,KAAK,CAAE,SAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,YDwFY,CCxFZ,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,YDwFc,CAsCd,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,YDwFY,CCxFZ,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,YDwFc,CAsCd,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,YDwFY,CCxFZ,OAAO,AAgCR,WAAW,CDwDV,ACxFF,YDwFc,CAsCd,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,YDwFY,CCxFZ,OAAO,CDwFP,ACxFF,YDwFc,CAsCd,QAAQ,AC9HV,CACE,KAAK,CAAE,GAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,YDwFY,CCxFZ,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,YDwFc,CAsCd,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,YDwFY,CCxFZ,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,YDwFc,CAsCd,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,YDwFY,CCxFZ,OAAO,AAgCR,WAAW,CDwDV,ACxFF,YDwFc,CAsCd,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,YDwFY,CCxFZ,OAAO,CDwFP,ACxFF,YDwFc,CAsCd,QAAQ,AC9HV,CACE,KAAK,CAAE,GAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,YDwFY,CCxFZ,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,YDwFc,CAsCd,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,YDwFY,CCxFZ,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,YDwFc,CAsCd,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,YDwFY,CCxFZ,OAAO,AAgCR,WAAW,CDwDV,ACxFF,YDwFc,CAsCd,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,YDwFY,CCxFZ,OAAO,CDwFP,ACxFF,YDwFc,CAsCd,QAAQ,AC9HV,CACE,KAAK,CAAE,SAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,YDwFY,CCxFZ,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,YDwFc,CAsCd,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,YDwFY,CCxFZ,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,YDwFc,CAsCd,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,YDwFY,CCxFZ,OAAO,AAgCR,WAAW,CDwDV,ACxFF,YDwFc,CAsCd,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,YDwFY,CCxFZ,OAAO,CDwFP,ACxFF,YDwFc,CAsCd,QAAQ,AC9HV,CACE,KAAK,CAAE,SAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,YDwFY,CCxFZ,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,YDwFc,CAsCd,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,YDwFY,CCxFZ,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,YDwFc,CAsCd,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,YDwFY,CCxFZ,OAAO,AAgCR,WAAW,CDwDV,ACxFF,YDwFc,CAsCd,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,YDwFY,CCxFZ,OAAO,CDwFP,ACxFF,YDwFc,CAsCd,QAAQ,AC9HV,CACE,KAAK,CAAE,KAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,YDwFY,CCxFZ,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,YDwFc,CAsCd,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,YDwFY,CCxFZ,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,YDwFc,CAsCd,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,YDwFY,CCxFZ,OAAO,AAgCR,WAAW,CDwDV,ACxFF,YDwFc,CAsCd,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,AD4DD,AACI,gBADY,CACZ,OAAO,CADX,AACE,gBADc,CAgChB,QAAQ,AA/BN,CD1GJ,YAAY,CAAE,CAAE,CAChB,aAAa,CAAE,CAAE,CCyGmB,AADlC,AAGE,gBAHc,CAGd,IAAI,AAAJ,CACE,WAAW,CAAE,CAAE,CACf,YAAY,CAAE,CAAE,CACjB,AAGH,AAA8B,SAArB,AAAA,IAAI,CAAC,gBAAgB,AAAA,IAAI,AAAlC,CACE,WAAW,CAAE,CAAE,CACf,YAAY,CAAE,CAAE,CACjB,AAED,AAGI,kBAHc,CAGd,OAAO,CAHX,AAGE,kBAHgB,CAkBlB,QAAQ,AAfN,CDjHJ,YAAY,CADH,QAAQ,CAEjB,aAAa,CAFJ,QAAQ,CCkH8B,AAI7C,AAAA,gBAAgB,AAAhB,CFjHA,WAAW,CAAE,IAAK,CAClB,YAAY,CAAE,IAAK,CEkHlB,AAFD,AAAA,gBAAgB,CAAhB,AAAA,gBAAgB,AFrHZ,WAAW,AAAA,IAAK,CAAA,AAAA,YAAY,CAAE,CAChC,KAAK,CAAE,IAAK,CACZ,KAAK,CAAE,IAAK,CACb,AEuHD,AAAA,kBAAkB,CAClB,AAAA,cAAc,CACd,AAAA,cAAc,AAFd,CF5GF,QAAQ,CAAE,MAAO,CACjB,WAAW,CAAE,CAAE,CACf,YAAY,CAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CE2GT,CZID,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,IAAI,EY/DzB,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,QAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,QAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFhBV,EAAU,CI8EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,QAAU,CI2EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,GAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,GAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,IAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,GAAU,CI2EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,GAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,GAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,IAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,GAAU,CI2EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,QAAQ,AAAR,CHtEJ,KAAK,CDeO,GAAU,CIyDjB,AAIC,AAAA,aAAa,AAAb,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,GAAU,CE+Ed,AAED,AAAA,aAAa,AAAb,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,IAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,cAAc,AAAd,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,cAAc,AAAd,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,eAAe,AAAf,CF5DJ,WAAsB,CFbV,GAAU,CI2EjB,AApBD,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,SAAU,CIyDjB,AAIC,AAAA,cAAc,AAAd,CF3EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,SAAU,CE+Ed,AAED,AAAA,cAAc,AAAd,CF/EJ,QAAQ,CAAE,QAAS,CACnB,IAAe,CAHN,UAAU,CEmFd,AAMH,AAAA,gBAAgB,AAAhB,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AApBD,AAAA,SAAS,AAAT,CHtEJ,KAAK,CDeO,IAAU,CIyDjB,AAgBD,AAAA,gBAAgB,AAAhB,CF5DJ,WAAsB,CFbV,SAAU,CI2EjB,AAKD,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,IAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,GAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,SAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,GAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,GAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,SAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,SAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,ADsDC,ACxFA,WDwFW,CCxFX,OAAO,CDwFP,ACxFF,WDwFa,CAsCb,QAAQ,AC9HV,CACE,KAAK,CAAE,KAAU,CACjB,KAAK,CR8E8C,IAAI,CQ7CxD,ADqDG,ACxFA,WDwFW,CCxFX,OAAO,AAwBR,YAAa,CAAA,EAAE,EDgEd,ACxFF,WDwFa,CAsCb,QAAQ,ACtGP,YAAa,CAAA,EAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CACb,AD8DC,ACxFA,WDwFW,CCxFX,OAAO,AA4BR,YAAa,CAAA,IAAI,ED4DhB,ACxFF,WDwFa,CAsCb,QAAQ,AClGP,YAAa,CAAA,IAAI,CAAlB,CACE,KAAK,CAAE,IAAK,CACb,AD0DC,ACxFA,WDwFW,CCxFX,OAAO,AAgCR,WAAW,CDwDV,ACxFF,WDwFa,CAsCb,QAAQ,AC9FP,WAAW,AAAC,CACX,KAAK,CR+C4C,IAAI,CQ9CtD,AD4DD,AACI,eADW,CACX,OAAO,CADX,AACE,eADa,CAgCf,QAAQ,AA/BN,CD1GJ,YAAY,CAAE,CAAE,CAChB,aAAa,CAAE,CAAE,CCyGmB,AADlC,AAGE,eAHa,CAGb,IAAI,AAAJ,CACE,WAAW,CAAE,CAAE,CACf,YAAY,CAAE,CAAE,CACjB,AAGH,AAA6B,SAApB,AAAA,IAAI,CAAC,eAAe,AAAA,IAAI,AAAjC,CACE,WAAW,CAAE,CAAE,CACf,YAAY,CAAE,CAAE,CACjB,AAED,AAGI,iBAHa,CAGb,OAAO,CAHX,AAGE,iBAHe,CAkBjB,QAAQ,AAfN,CDjHJ,YAAY,CADH,QAAQ,CAEjB,aAAa,CAFJ,QAAQ,CCkH8B,AAI7C,AAAA,eAAe,AAAf,CFjHA,WAAW,CAAE,IAAK,CAClB,YAAY,CAAE,IAAK,CEkHlB,AAFD,AAAA,eAAe,CAAf,AAAA,eAAe,AFrHX,WAAW,AAAA,IAAK,CAAA,AAAA,YAAY,CAAE,CAChC,KAAK,CAAE,IAAK,CACZ,KAAK,CAAE,IAAK,CACb,AEuHD,AAAA,iBAAiB,CACjB,AAAA,aAAa,CACb,AAAA,aAAa,AAFb,CF5GF,QAAQ,CAAE,MAAO,CACjB,WAAW,CAAE,CAAE,CACf,YAAY,CAAE,CAAE,CAChB,KAAK,CAAE,IAAK,CE2GT,CqD/IL,AAAA,SAAS,AhE6IN,QAAQ,CgE7IX,AAAA,SAAS,AhE8IN,OAAO,AAAC,CACP,OAAO,CAAE,GAAI,CACb,OAAO,CAAE,KAAM,CAKhB,AgErJH,AAAA,SAAS,AhEuJN,OAAO,AAAC,CACP,KAAK,CAAE,IAAK,CACb,AgErJH,AACI,IADA,AAAA,GAAG,CACH,MAAM,CADV,AACY,IADR,AAAA,GAAG,CACK,aAAa,AAAC,CAClB,OAAO,CAAE,IAAK,CACjB,AAGL,AACI,IADA,AAAA,MAAM,CACN,GAAG,CADP,AACS,IADL,AAAA,MAAM,CACD,eAAe,AAAC,CACjB,OAAO,CAAE,IAAK,CACjB,AAGL,AAAA,iBAAiB,AAAC,CACd,aAAa,CAAE,YAAa,CAC/B,AAED,AAAA,cAAc,AAAC,CACX,UAAU,CAAE,YAAa,CAC5B,AAED,AAAA,UAAU,AAAC,CACP,MAAM,CAAE,YAAa,CACxB,AAED,AAAA,YAAY,AAAC,CACT,UAAU,CAAE,MAAO,CACtB,AAED,AAAA,WAAW,AAAC,CACR,UAAU,CAAE,KAAM,CACrB,AAED,AAAA,eAAe,AAAC,CACZ,QAAQ,CAAE,QAAS,CACnB,QAAQ,CAAE,MAAO,CACjB,IAAI,CAAE,aAAI,CACV,MAAM,CAAE,GAAI,CAAE,KAAK,CAAE,GAAI,CACzB,MAAM,CAAE,IAAK,CAAE,OAAO,CAAE,CAAE,CAAE,MAAM,CAAE,CAAE,CACzC,AAED,AAAA,cAAc,AAAC,CACX,QAAQ,CAAE,mBAAoB,CAC9B,KAAK,CAAE,GAAI,CACX,MAAM,CAAE,GAAI,CACZ,QAAQ,CAAE,MAAO,CACjB,IAAI,CAAE,gBAAI,CACV,KAAK,C/DAQ,OAAO,C+D8BvB,AApCD,AAAA,cAAc,AAQT,OAAO,CARZ,AAAA,cAAc,AAQC,MAAM,AAAC,CACd,OAAO,CAAE,IAAK,CACd,QAAQ,CAAE,iBAAkB,CAC5B,MAAM,CAAE,IAAK,CACb,KAAK,CAAE,IAAK,CACZ,QAAQ,CAAE,OAAQ,CAClB,IAAI,CAAE,IAAK,CACd,AAfL,AAAA,cAAc,AAiBT,MAAM,AAAC,CACJ,KAAK,C/DZI,OAAO,C+DanB,AAnBL,AAAA,cAAc,AAqBT,SAAS,AAAA,OAAO,CArBrB,AAAA,cAAc,AAqBU,SAAS,AAAA,MAAM,AAAC,CAChC,QAAQ,CAAE,mBAAoB,CAC9B,GAAG,CAAE,CAAE,CACP,IAAI,CAAE,CAAE,CACR,KAAK,CAAE,CAAE,CACT,MAAM,CAAE,IAAK,CACb,UAAU,CAAE,MAAO,CACnB,WAAW,CAAE,CAAE,CACf,OAAO,CAAE,IAAK,CACd,UAAU,CAAE,IAAK,CACpB,AA/BL,AAAA,cAAc,AAiCT,MAAM,AAAC,CACJ,eAAe,CAAE,SAAU,CAC9B,AI3CL,AJ+DA,II/DI,AAAA,UAAU,CAMV,KAAK,CAAA,AAAA,GAAC,CAAI,oBAAoB,AAAxB,CJyDS,CAhBjB,QAAQ,CAAE,mBAAoB,CAC9B,IAAI,CAAE,qBAAI,CACV,IAAI,CAAE,wBAAI,CACV,OAAO,CAAC,YAAa,CACrB,MAAM,CAAC,YAAa,CACpB,MAAM,CAAE,cAAe,CACvB,KAAK,CAAE,cAAe,CACtB,QAAQ,CAAE,MAAO,CAWlB,AATC,AACE,IADE,AAAA,MAAM,CIxDZ,IAAI,AAAA,UAAU,CAMV,KAAK,CAAA,AAAA,GAAC,CAAI,oBAAoB,AAAxB,EJmDN,CAAC,CIzDL,AJyDI,IIzDA,AAAA,UAAU,CJwDZ,IAAI,AAAA,MAAM,CIlDR,KAAK,CAAA,AAAA,GAAC,CAAI,oBAAoB,AAAxB,EJmDN,CAAC,CADH,AACK,IADD,AAAA,MAAM,CIxDZ,IAAI,AAAA,UAAU,CAMV,KAAK,CAAA,AAAA,GAAC,CAAI,oBAAoB,AAAxB,EJmDH,KAAK,CIzDZ,AJyDO,IIzDH,AAAA,UAAU,CJwDZ,IAAI,AAAA,MAAM,CIlDR,KAAK,CAAA,AAAA,GAAC,CAAI,oBAAoB,AAAxB,EJmDH,KAAK,CADV,AACY,IADR,AAAA,MAAM,CIxDZ,IAAI,AAAA,UAAU,CAMV,KAAK,CAAA,AAAA,GAAC,CAAI,oBAAoB,AAAxB,EJmDI,MAAM,CIzDpB,AJyDc,IIzDV,AAAA,UAAU,CJwDZ,IAAI,AAAA,MAAM,CIlDR,KAAK,CAAA,AAAA,GAAC,CAAI,oBAAoB,AAAxB,EJmDI,MAAM,AAAC,CACf,OAAO,CAAE,eAAgB,CAC1B,AC9FL,AAAA,SAAS,CAAE,AAAA,YAAY,AAAC,CACpB,OAAO,CAAE,CAAE,CACd,AAED,AAAA,WAAW,AAAC,CACR,OAAO,CAAE,CAAE,CACX,UAAU,CAAE,wBAAyB,CACxC,AAED,AAAU,MAAJ,CAAC,GAAG,AAAA,SAAS,AAAC,CAChB,OAAO,CAAE,IAAK,CACjB,ACZD,AAAA,IAAI,AAAC,CACD,MAAM,CAAE,CAAE,CASb,AAVD,AAGI,IAHA,CAGA,SAAS,AAAC,CACN,KAAK,CjEkDE,OAAO,CiEjDjB,AALL,AAOI,IAPA,CAOA,KAAK,CAPT,AAOW,IAPP,CAOO,QAAQ,AAAC,CACZ,SAAS,CjEsCA,IAAI,CiErChB,AAIL,AAAA,OAAO,CAAE,AAAO,OAAA,AAAA,MAAM,CAAE,AAAmB,KAAd,CAAA,AAAA,IAAC,CAAK,QAAQ,AAAb,CAAe,CACzC,eAAe,CAAE,QAAS,CAC1B,UAAU,CAAE,oCAAqC,CACjD,aAAa,CjEqDD,CAAC,CiEpDb,KAAK,CAAE,IAAK,CACZ,WAAW,CjEkDM,GAAG,CiEjDpB,OAAO,CxEkEC,OAAU,CAAV,IAAU,CwElCrB,AAtCD,AAAA,OAAO,AAQF,MAAM,CARF,AAAO,OAAA,AAAA,MAAM,AAQjB,MAAM,CARa,AAAmB,KAAd,CAAA,AAAA,IAAC,CAAK,QAAQ,AAAb,CAQzB,MAAM,AAAC,CACJ,mBAAmB,CAAE,IAAK,CAC7B,AAVL,AAYI,OAZG,CAYH,GAAG,CAZE,AAYL,OAZY,AAAA,MAAM,CAYlB,GAAG,CAZiB,AAYpB,KAZyB,CAAA,AAAA,IAAC,CAAK,QAAQ,AAAb,EAY1B,GAAG,AAAC,CACA,IAAI,CAAE,IAAK,CACX,MAAM,CxE0DF,MAAU,CwEzDd,KAAK,CxEyDD,IAAU,CwExDjB,AAhBL,AAAA,OAAO,AAkBF,cAAc,CAlBV,AAAO,OAAA,AAAA,MAAM,AAkBjB,cAAc,CAlBK,AAAmB,KAAd,CAAA,AAAA,IAAC,CAAK,QAAQ,AAAb,CAkBzB,cAAc,AAAC,CACZ,MAAM,CxE0DF,CAAC,CALD,QAAU,CAKV,CAAC,CALD,OAAU,CwEpDjB,AApBL,AAAA,OAAO,AAsBF,aAAa,CAtBT,AAAO,OAAA,AAAA,MAAM,AAsBjB,aAAa,CAtBM,AAAmB,KAAd,CAAA,AAAA,IAAC,CAAK,QAAQ,AAAb,CAsBzB,aAAa,AAAC,CACX,MAAM,CxEsDF,CAAC,CALD,OAAU,CAKV,CAAC,CALD,QAAU,CwEhDjB,AAxBL,AAAA,OAAO,AAiCF,QAAQ,CAjCJ,AAAO,OAAA,AAAA,MAAM,AAiCjB,QAAQ,CAjCW,AAAmB,KAAd,CAAA,AAAA,IAAC,CAAK,QAAQ,AAAb,CAiCzB,QAAQ,AAAC,CACN,gBAAgB,CAAE,WAAY,CAC9B,MAAM,CxEqCF,QAAU,CwErCC,KAAK,CAEvB,AClDL,AAAA,IAAI,CAAE,AAAA,IAAI,AAAC,CACP,MAAM,CAAE,CAAE,CACV,OAAO,CAAE,CAAE,CACX,MAAM,CAAE,IAAK,CACb,UAAU,ClEyDI,OAAO,CkExDxB,AACD,AAAA,IAAI,AAAC,CACD,UAAU,CAAE,OAAQ,CACpB,OAAO,CAAE,CAAE,CACX,sBAAsB,CAAE,WAAY,CACpC,SAAS,ClEoCI,IAAI,CkEnCpB,AAED,AAAA,CAAC,AAAC,CACE,UAAU,CAAE,UAAW,CAC1B,AAED,AAAA,eAAe,AAAC,CACZ,QAAQ,CAAE,QAAS,CACnB,GAAG,CAAE,CAAE,CACP,IAAI,CAAE,CAAE,CACR,KAAK,CAAE,CAAE,CACT,MAAM,CAAE,OAAQ,CAChB,UAAU,CAAE,IAAK,CACjB,KAAK,CAAE,IAAK,CACZ,OAAO,CAAE,OAAQ,CACjB,UAAU,CAAE,MAAO,CACtB,AAED,AAAA,YAAY,AAAC,CACT,OAAO,CAAE,IAAK,CACd,cAAc,CAAE,MAAO,CACvB,KAAK,CAAE,IAAK,CAQf,ApE2GG,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,IAAI,EoEtH/B,AAAA,YAAY,AAAC,CAML,QAAQ,CAAE,QAAS,CACnB,GAAG,CAAE,CAAE,CACP,IAAI,CAAE,CAAE,CACR,MAAM,CAAE,IAAK,CAEpB,CAED,AAAA,YAAY,AAAC,CACT,KAAK,CAAE,IAAK,CACZ,UAAU,CAAE,WAAY,CAiB3B,ApEsFG,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,SAAS,EoEzGpC,AAAA,YAAY,AAAC,CAKL,KAAK,CAAE,CAAE,CAchB,CpEsFG,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,IAAI,EoEzG/B,AAAA,YAAY,AAAC,CASL,QAAQ,CAAE,QAAS,CACnB,GAAG,CAAE,CAAE,CACP,KAAK,CAAE,CAAE,CACT,IAAI,CzE+BA,QAAU,CyE9Bd,KAAK,CAAE,IAAK,CACZ,IAAI,CAAE,IAAK,CACX,WAAW,CzE4BP,MAAU,CyE3Bd,aAAa,CAAE,sBAAI,CACnB,KAAK,CzE0BD,QAAU,CyExBrB,CAED,AAAA,YAAY,AAAC,CACT,OAAO,CzE0BC,CAAC,CALD,OAAU,CyEhBrB,ApE8EG,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,IAAI,EoEpF/B,AAAA,YAAY,AAAC,CAIL,OAAO,CzEuBH,CAAC,CALD,QAAU,CyEhBrB,CAED,AAAK,KAAA,AAAA,QAAQ,AAAC,CACV,UAAU,CAAE,WAAY,CAU3B,ApEiEG,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,IAAI,EoE5E/B,AAAK,KAAA,AAAA,QAAQ,AAAC,CAIN,QAAQ,CAAE,KAAM,CAChB,GAAG,CAAE,CAAE,CACP,IAAI,CAAE,CAAE,CACR,KAAK,CzEOD,QAAU,CyENd,MAAM,CAAE,IAAK,CACb,YAAY,CAAE,sBAAI,CAEzB,CAED,AACI,WADO,CACP,CAAC,AAAC,CACE,SAAS,ClE2CC,GAAG,CkE1ChB,ACrFL,AAAA,WAAW,AAAC,CACR,MAAM,C1EkFE,SAAU,C0EhFlB,OAAO,CAAE,IAAK,CACd,cAAc,CAAE,GAAI,CACpB,SAAS,CAAE,MAAO,CAClB,eAAe,CAAE,aAAc,CAC/B,OAAO,C1EiFC,CAAC,CALD,QAAU,C0E3ElB,KAAK,CATe,IAAI,CAWxB,UAAU,CnEiDI,OAAO,CmEhDrB,aAAa,CAAE,GAAG,CAAC,KAAK,CAAC,gBAAI,CAoBhC,AA/BD,AAaI,WAbO,CAaP,YAAY,AAAC,CACT,OAAO,CAAE,IAAK,CACd,WAAW,CAAE,MAAO,CACpB,WAAW,CAAE,MAAO,CACpB,SAAS,C1EkEL,OAAU,C0E7DjB,ArE2HD,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,IAAI,EqEjJ/B,AAaI,WAbO,CAaP,YAAY,AAAC,CAOL,OAAO,CAAE,IAAK,CAErB,CrE2HD,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,IAAI,EqEjJ/B,AAAA,WAAW,AAAC,CAyBJ,QAAQ,CAAE,QAAS,CACnB,GAAG,CAAE,CAAE,CACP,IAAI,CAAE,CAAE,CACR,KAAK,CAAE,CAAE,CACT,OAAO,C1E2DH,CAAC,CALD,SAAU,C0EpDrB,CAGD,AAAI,IAAA,AAAA,UAAU,AAAC,CACX,QAAQ,CAAE,QAAS,CACnB,KAAK,CAAE,IAAK,CACZ,MAAM,CAAE,CAAE,CACV,OAAO,CAAE,CAAE,CAyCd,AA7CD,AAUuB,IAVnB,AAAA,UAAU,CAUV,KAAK,CAAA,AAAA,IAAC,CAAK,QAAQ,AAAb,CAAe,CACjB,OAAO,CAAE,KAAM,CACf,KAAK,CAAE,IAAK,CACZ,SAAS,C1EoCL,QAAU,C0EnCd,MAAM,CAAE,IAAK,CACb,OAAO,C1EkCH,SAAU,CAAV,SAAU,CAAV,SAAU,CAAV,QAAU,C0EjCd,MAAM,CAAE,GAAG,CAAC,KAAK,CnESP,OAAO,CmERjB,UAAU,CAAE,4BAA6B,CACzC,UAAU,CnEOA,OAAO,CmEDpB,AAxBL,AAUuB,IAVnB,AAAA,UAAU,CAUV,KAAK,CAAA,AAAA,IAAC,CAAK,QAAQ,AAAb,CAUD,MAAM,AAAC,CACJ,OAAO,CAAE,IAAK,CACd,YAAY,CnEPL,OAAO,CmEQjB,AAvBT,AA0BI,IA1BA,AAAA,UAAU,CA0BV,OAAO,AAAC,CACJ,QAAQ,CAAE,QAAS,CACnB,GAAG,CAAE,CAAE,CACP,IAAI,CAAE,CAAE,CACR,KAAK,C1EmBD,MAAU,C0ElBd,MAAM,CAAE,IAAK,CACb,OAAO,CAAE,CAAE,CACX,UAAU,CAAE,WAAY,CACxB,MAAM,CAAE,IAAK,CACb,OAAO,CAAE,IAAK,CACd,KAAK,CAvEW,IAAI,CA+EvB,AA5CL,AAsCQ,IAtCJ,AAAA,UAAU,CA0BV,OAAO,CAYH,GAAG,AAAC,CACA,IAAI,CA1EQ,IAAI,CA2EhB,MAAM,CAAE,IAAK,CACb,KAAK,CAAE,IAAK,CACZ,UAAU,C1EOV,MAAU,C0ENb,AC/ET,AAAA,YAAY,AAAC,CACT,gBAAgB,CpE4DF,OAAO,CoE3DxB,AAED,AAAA,EAAE,CAAC,AAAA,EAAE,CAAC,AAAA,EAAE,CAAC,AAAA,EAAE,CAAC,AAAA,EAAE,CAAC,AAAA,EAAE,AAAC,CACd,UAAU,CAAE,MAAwB,CACpC,aAAa,CpE8HS,IAAI,CoE7H1B,WAAW,CpEgGM,WAAW,CAAE,UAAU,CoE/FxC,WAAW,CAAE,GAAI,CACjB,WAAW,CpEqHK,GAAG,CoEpHnB,cAAc,CpEsHM,kBAAkB,CoErHtC,KAAK,CpEuCQ,OAAO,CoEtCvB,AAGG,AAAA,EAAE,AAAF,CACI,SAAS,C3EqEL,OAAU,C2EpEjB,AAFD,AAAA,EAAE,AAAF,CACI,SAAS,C3EqEL,QAAU,C2EpEjB,AAFD,AAAA,EAAE,AAAF,CACI,SAAS,C3EqEL,MAAU,C2EpEjB,AAFD,AAAA,EAAE,AAAF,CACI,SAAS,C3EqEL,QAAU,C2EpEjB,AAFD,AAAA,EAAE,AAAF,CACI,SAAS,C3EqEL,OAAU,C2EpEjB,AAFD,AAAA,EAAE,AAAF,CACI,SAAS,C3EqEL,QAAU,C2EpEjB,AAGL,AAAA,EAAE,AAAC,CACC,UAAU,CAAE,MAAwB,CACvC,AAED,AAAA,CAAC,CAAE,AAAA,EAAE,CAAE,AAAA,EAAE,AAAC,CACN,MAAM,CAAE,CAAC,CAAC,CAAC,CpE2GW,IAAI,CoE1G1B,SAAS,C3E2DD,QAAU,C2E1DlB,WAAW,CpEwGQ,GAAG,CoEvGtB,cAAc,CpEyGS,kBAAkB,CoExG5C,AAED,AAAA,CAAC,AAAC,CACE,KAAK,CpEkBQ,OAAO,CoEjBpB,MAAM,CAAE,OAAQ,CAChB,WAAW,CpEkCM,GAAG,CoEjCpB,eAAe,CAAE,IAAK,CACtB,UAAU,CAAE,qBAAsB,CAIrC,AATD,AAAA,CAAC,AAMI,MAAM,AAAC,CACJ,KAAK,CpEaM,OAAO,CoEZrB,AAGL,AAAA,KAAK,AAAC,CACF,MAAM,CAAE,cAAe,CACvB,aAAa,CAAE,GAAI,CACnB,cAAc,CAAE,CAAE,CAkBrB,AArBD,AAKI,KALC,CAKD,EAAE,AAAC,CACC,eAAe,CAAE,QAAS,CAC7B,AAPL,AASI,KATC,CASD,EAAE,AAAC,CACC,UAAU,CAAE,IAAK,CACjB,WAAW,CAAE,MAAO,CACvB,AAZL,AAaI,KAbC,CAaD,EAAE,CAbN,AAaQ,KAbH,CAaG,EAAE,AAAC,CACH,OAAO,CAAE,KAAM,CACf,aAAa,CAAE,cAAe,CAC9B,cAAc,CAAE,GAAI,CACvB,AAjBL,AAkBI,KAlBC,CAkBD,EAAE,AAAC,CACC,mBAAmB,CAAE,GAAI,CAC5B,AC9DL,AAAK,KAAA,AAAA,QAAQ,AAAC,CACV,UAAU,CrEiDG,OAAO,CqEhDpB,KAAK,CAAE,IAAK,CACZ,WAAW,CAAE,CAAC,CAAC,CAAC,C5EkFR,QAAU,C4ElFO,gBAAI,CAKhC,AvE2IG,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,IAAI,EuEnJ/B,AAAK,KAAA,AAAA,QAAQ,AAAC,CAMN,YAAY,CAAE,iBAAkB,CAEvC,CAED,AAAA,KAAK,AAAC,CACF,OAAO,CAAE,KAAM,CACf,MAAM,CAAE,CAAE,CACV,WAAW,CAAE,IAAK,CAClB,WAAW,CAAE,MAAO,CACpB,QAAQ,CAAE,MAAO,CAiBpB,AAtBD,AAOI,KAPC,CAOD,CAAC,AAAC,CACE,OAAO,CAAE,KAAM,CACf,KAAK,C5EkED,KAAU,C4EjEd,MAAM,C5EiEF,QAAU,C4EhEd,MAAM,C5EgEF,QAAU,C4EhEE,IAAI,C5EgEhB,QAAU,CAAV,QAAU,C4E9Dd,UAAU,CAAE,WAAW,CAAiE,iEAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CACjH,eAAe,CAAE,IAAK,CAOzB,AvEoHD,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,IAAI,EuEzI/B,AAOI,KAPC,CAOD,CAAC,AAAC,CAUM,KAAK,C5E0DL,OAAU,C4EzDV,MAAM,C5EyDN,SAAU,C4ExDV,MAAM,C5EwDN,SAAU,C4ExDM,IAAI,C5EwDpB,QAAU,CAAV,QAAU,C4EtDjB,CAIL,AAAM,MAAA,AAAA,SAAS,AAAC,CACZ,OAAO,CAAE,GAAI,CACb,OAAO,CAAE,KAAM,CACf,UAAU,CrEYG,OAAO,CqEXpB,OAAO,C5E8CC,QAAU,CAAV,SAAU,CAAV,OAAU,CAAV,SAAU,C4E7ClB,KAAK,C5E6CG,OAAU,C4E5ClB,MAAM,C5E4CE,OAAU,C4E3ClB,QAAQ,CAAE,KAAM,CAChB,GAAG,CAAE,CAAE,CACP,KAAK,CAAE,CAAE,CACT,MAAM,CAAE,IAAK,CACb,UAAU,CAAE,IAAK,CACjB,MAAM,CAAE,OAAQ,CAChB,OAAO,CAAE,IAAK,CA+CjB,AvEoDG,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,IAAI,EuEhH/B,AAAM,MAAA,AAAA,SAAS,AAAC,CAgBR,OAAO,CAAE,IAAK,CA4CrB,CA5DD,AAmBI,MAnBE,AAAA,SAAS,CAmBX,eAAe,AAAC,CACZ,QAAQ,CAAE,QAAS,CACnB,IAAI,CAAE,QAAS,CACf,KAAK,CAAC,GAAI,CACV,MAAM,CAAE,GAAI,CACf,AAxBL,AA0BI,MA1BE,AAAA,SAAS,CA0BX,IAAI,AAAC,CACD,KAAK,CAAE,IAAK,CACZ,cAAc,CAAE,SAAU,CAC1B,SAAS,C5EqBL,QAAU,C4EpBd,OAAO,CAAE,KAAM,CACf,UAAU,C5EmBN,QAAU,C4ElBjB,AAhCL,AAkCI,MAlCE,AAAA,SAAS,CAkCX,GAAG,AAAC,CACA,IAAI,CAAE,IAAK,CACd,AApCL,AAuCQ,MAvCF,AAAA,SAAS,AAsCV,OAAO,CACJ,KAAK,AAAC,CACF,QAAQ,CAAE,QAAS,CACnB,IAAI,CAAE,QAAS,CACf,KAAK,CAAC,GAAI,CACV,MAAM,CAAE,GAAI,CACf,AA5CT,AA6CQ,MA7CF,AAAA,SAAS,AAsCV,OAAO,CAOJ,eAAe,AAAC,CACZ,QAAQ,CAAE,MAAO,CACjB,KAAK,CAAE,IAAK,CACZ,MAAM,CAAE,IAAK,CAChB,AAjDT,AAkDQ,MAlDF,AAAA,SAAS,AAsCV,OAAO,CAYJ,OAAO,AAAC,CACJ,SAAS,CAAE,aAAM,CAAQ,oBAAS,CACrC,AApDT,AAqDQ,MArDF,AAAA,SAAS,AAsCV,OAAO,CAeJ,OAAO,AAAC,CACJ,OAAO,CAAE,CAAE,CACd,AAvDT,AAwDQ,MAxDF,AAAA,SAAS,AAsCV,OAAO,CAkBJ,OAAO,AAAC,CACJ,SAAS,CAAE,cAAM,CAAS,sBAAS,CACtC,AAIT,AAAG,GAAA,AAAA,QAAQ,AAAC,CACR,OAAO,CAAE,IAAK,CA+GjB,AAhHD,AAAG,GAAA,AAAA,QAAQ,AAGN,OAAO,AAAC,CACL,OAAO,CAAE,KAAM,CACf,QAAQ,CAAE,KAAM,CAChB,GAAG,CAAE,CAAE,CACP,IAAI,CAAE,CAAE,CACR,KAAK,CAAE,CAAE,CACT,KAAK,CAAE,IAAK,CACZ,MAAM,CAAE,KAAM,CACd,UAAU,CAAE,MAAO,CACnB,UAAU,CAAE,MAAO,CACnB,0BAA0B,CAAE,KAAM,CAClC,UAAU,CrE7DD,OAAO,CqE8DhB,OAAO,C5E3BH,QAAU,C4E4BjB,AvEkCD,MAAM,CAAN,MAAM,MAAM,SAAS,EAAE,IAAI,EuElD/B,AAAG,GAAA,AAAA,QAAQ,AAAC,CAmBJ,OAAO,CAAE,KAAM,CA6FtB,CAhHD,AAsBI,GAtBD,AAAA,QAAQ,CAsBP,EAAE,AAAC,CACC,OAAO,CAAE,KAAM,CACf,MAAM,CAAE,CAAE,CACV,OAAO,CAAE,CAAE,CACX,UAAU,CAAE,IAAK,CACjB,SAAS,C5EvCL,IAAU,C4EyCjB,AA7BL,AA+BI,GA/BD,AAAA,QAAQ,CA+BP,GAAG,AAAC,CACA,IAAI,CAAE,IAAK,CACX,KAAK,C5E7CD,QAAU,C4E8Cd,MAAM,C5E9CF,QAAU,C4E+Cd,cAAc,CAAE,MAAO,CACvB,QAAQ,CAAE,QAAS,CACnB,GAAG,CAAE,IAAK,CACV,YAAY,CAAE,GAAI,CACrB,AAvCL,AA4Cc,GA5CX,AAAA,QAAQ,CAyCL,EAAE,CACE,EAAE,CAEE,CAAC,AAAC,CACA,WAAW,C5EzDf,QAAU,C4E0DN,WAAW,CrE3EN,GAAG,CqE4EX,AA/Cb,AAuDI,GAvDD,AAAA,QAAQ,CAuDP,EAAE,AAAC,CACC,OAAO,CAAE,KAAM,CACf,MAAM,CAAE,CAAE,CACV,OAAO,CAAE,CAAE,CAMd,AAhEL,AAmEI,GAnED,AAAA,QAAQ,CAmEP,CAAC,AAAC,CACE,OAAO,CAAE,KAAM,CACf,OAAO,C5EjFH,OAAU,CAAV,QAAU,C4EkFd,KAAK,CAAE,IAAK,CAWf,AAjFL,AAmEI,GAnED,AAAA,QAAQ,CAmEP,CAAC,AAWI,MAAM,AAAC,CACJ,KAAK,CrE7HE,OAAO,CqE8HjB,AAhFT,AAoF0B,GApFvB,AAAA,QAAQ,CAoFL,EAAE,CAAG,EAAE,CAAG,EAAE,CAAG,EAAE,CAAG,CAAC,AAAC,CACpB,YAAY,C5EjGR,SAAU,C4EkGd,SAAS,C5ElGL,MAAU,C4EmGd,cAAc,CAAE,SAAU,CAO7B,AA9FL,AAiGa,GAjGV,AAAA,QAAQ,CAiGP,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,AAAC,CACP,YAAY,C5E9GR,OAAU,C4E+Gd,SAAS,C5E/GL,MAAU,C4EgHd,WAAW,CrElII,GAAG,CqEmIrB,AArGL,AAwGgB,GAxGb,AAAA,QAAQ,CAwGP,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,AAAC,CACV,YAAY,C5ErHR,SAAU,C4EsHjB,AA1GL,AA6GmB,GA7GhB,AAAA,QAAQ,CA6GP,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,AAAC,CACb,YAAY,C5E1HR,QAAU,C4E2HjB,AAGL,AAAA,IAAI,AAAC,CACD,MAAM,CAAE,CAAE,CACV,OAAO,CAAE,CACZ,CAAC,AACF,AAAA,WAAW,AAAC,CACR,OAAO,CAAE,YAAa,CACtB,QAAQ,CAAE,QAAS,CACnB,KAAK,CAAE,IAAK,CACZ,WAAW,CAAE,KAChB,CAAC,AACF,AAAW,WAAA,AAAA,OAAO,AAAC,CACf,QAAQ,CAAE,QAAS,CACnB,OAAO,CAAE,KAAM,CACf,OAAO,CAAE,EAAG,CACZ,MAAM,CAAE,eAAgB,CACxB,IAAI,CAAE,GAAI,CACV,GAAG,CAAE,GAAI,CACT,KAAK,CAAE,IAAK,CACZ,MAAM,CAAE,IAAK,CACb,YAAY,CAAE,gBAAiB,CAC/B,UAAU,CAAE,mBAAoB,CAChC,iBAAiB,CAAE,aAAM,CACzB,SAAS,CAAE,aAAM,CACjB,2BAA2B,CAAE,GAAI,CACjC,mBAAmB,CAAE,GACxB,CAAC,AACF,AAAA,UAAU,AAAC,CACP,OAAO,CAAE,KACZ,CAAC,AACF,AAAW,UAAD,CAAC,CAAC,AAAC,CACT,OAAO,CAAE,KAAM,CAClB,AACD,AAAK,IAAD,CAAC,IAAI,AAAC,CACN,OAAO,CAAE,IAAK,CACjB,AACD,AAA+B,GAA5B,AAAA,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAChC,AAA6B,GAA1B,AAAA,QAAQ,CAAC,gBAAgB,CAAC,CAAC,AAAC,CAC3B,WAAW,CAAE,IAAK,CAClB,KAAK,CAAE,OAAQ,CAClB,AACD,AAAiB,gBAAD,CAAC,IAAI,AAAC,CAClB,OAAO,CAAE,KACZ,CAAC,AACF,AAA8B,gBAAd,CAAC,CAAC,CAAC,WAAW,AAAA,OAAO,AAAC,CAClC,iBAAiB,CAAE,cAAM,CACzB,SAAS,CAAE,cAAM,CACjB,UAAU,CAAE,MAAO,CACtB,AAED,AAAmC,QAA3B,CAAG,IAAI,CAAG,UAAU,CAAG,CAAC,CAAG,WAAW,AAAC,CAC3C,WAAW,CAAE,KAAM,CACnB,KAAK,CAAE,IAAK,CACZ,YAAY,CAAE,GAAI,CACrB,ACvQD,AAAc,aAAD,CAAC,GAAG,AAAC,CAChB,KAAK,CAAE,KAAM,CACd,AACD,AAAiB,aAAJ,CAAC,GAAG,AAAA,aAAa,AAAC,CAC7B,OAAO,CAAE,IAAK,CACf,AACD,AAAc,aAAD,CAAC,CAAC,AAAC,CACd,SAAS,CAAE,GAAI,CAChB,AACD,AAAe,aAAF,CAAC,CAAC,AAAA,aAAa,AAAC,CAC3B,OAAO,CAAE,KAAM,CACf,SAAS,CAAE,IAAK,CACjB,ACTD,AAAA,KAAK,AAAC,CACJ,OAAO,CAAE,KAAM,CACf,UAAU,CAAE,IAAK,CACjB,OAAO,CAAE,KAAM,CACf,UAAU,CAAE,OAAQ,CACpB,KAAK,CAAE,OAAQ,CAChB,AAED,AAAA,aAAa,CACb,AAAA,WAAW,AAAC,CACV,KAAK,CAAE,OAAQ,CAChB,AAGD,AAAA,aAAa,CACb,AAAA,kBAAkB,CAClB,AAAA,cAAc,AAAC,CACb,KAAK,CAAE,OAAQ,CAChB,AAGD,AAAA,YAAY,CACZ,AAAA,YAAY,CACZ,AAAW,UAAD,CAAC,iBAAiB,CAC5B,AAAA,aAAa,CACb,AAAA,YAAY,CACZ,AAAA,YAAY,AAAC,CACX,KAAK,CAAE,OAAQ,CAChB,AAGD,AAAA,WAAW,CACX,AAAA,aAAa,CACb,AAAA,UAAU,CACV,AAAA,iBAAiB,CACjB,AAAA,oBAAoB,AAAC,CACnB,KAAK,CAAE,OAAQ,CAChB,AAGD,AAAA,eAAe,CACf,AAAA,UAAU,CACV,AAAA,cAAc,CACd,AAAA,uBAAuB,CACvB,AAAY,WAAD,CAAC,WAAW,CACvB,AAAA,UAAU,AAAC,CACT,KAAK,CAAE,OAAQ,CAChB,AAGD,AAAA,YAAY,CACZ,AAAA,YAAY,CACZ,AAAA,WAAW,CACX,AAAA,UAAU,CACV,AAAW,UAAD,CAAC,aAAa,CACxB,AAAA,mBAAmB,CACnB,AAAA,qBAAqB,CACrB,AAAA,UAAU,AAAC,CACT,KAAK,CAAE,OAAQ,CAChB,AAGD,AAAA,cAAc,CACd,AAAA,cAAc,AAAC,CACb,KAAK,CAAE,OAAQ,CAChB,AAED,AAAA,aAAa,AAAC,CACZ,UAAU,CAAE,OAAQ,CACrB,AAED,AAAA,cAAc,AAAC,CACb,UAAU,CAAE,MAAO,CACpB,AAED,AAAA,YAAY,AAAC,CACX,WAAW,CAAE,IAAK,CACnB,AC9ED,AAAA,qBAAqB,AAAC,CACpB,WAAW,CAAC,GAAI,CAChB,SAAS,CAAC,IAAK,CACf,WAAW,CAAE,GAAI,CACjB,KAAK,CAAE,IAAK,CACZ,MAAM,CAAE,KAAM,CACf,AAED,AAAsB,qBAAD,CAAC,CAAC,AAAC,CACtB,KAAK,CAAE,IAAK,CACZ,eAAe,CAAE,IAAK,CACvB,AAED,AAAuB,qBAAF,CAAC,CAAC,AAAA,MAAM,AAAC,CAC5B,KAAK,CAAE,IAAK,CACb,AAED,AAAA,2BAA2B,AAAC,CAC1B,WAAW,CAAC,GAAI,CAChB,SAAS,CAAC,IAAK,CACf,WAAW,CAAE,GAAI,CACjB,KAAK,CAAE,IAAK,CACb,AAED,AAAA,2BAA2B,AAAC,CAC1B,WAAW,CAAC,GAAI,CAChB,SAAS,CAAC,IAAK,CACf,WAAW,CAAE,GAAI,CACjB,UAAU,CAAE,IAAK,CAClB,AAED,AAA4B,2BAAD,CAAC,CAAC,AAAC,CAC5B,KAAK,CAAE,IAAK,CACZ,eAAe,CAAE,IAAK,CACvB,AAED,AAA6B,2BAAF,CAAC,CAAC,AAAA,MAAM,AAAC,CAClC,KAAK,CAAE,IAAK,CACb,AAED,AAAA,yBAAyB,AAAC,CACxB,WAAW,CAAC,GAAI,CAChB,SAAS,CAAC,IAAK,CACf,WAAW,CAAE,GAAI,CACjB,SAAS,CAAE,UAAW,CACtB,OAAO,CAAE,IAAK,CACf,AAED,AAA0B,yBAAD,CAAC,CAAC,AAAC,CAC1B,KAAK,CAAE,IAAK,CACZ,eAAe,CAAE,IAAK,CACvB,AAED,AAA2B,yBAAF,CAAC,CAAC,AAAA,MAAM,AAAC,CAChC,KAAK,CAAE,IAAK,CACb,AAED,AAAA,0BAA0B,AAAC,CACzB,WAAW,CAAC,GAAI,CAChB,SAAS,CAAC,IAAK,CACf,WAAW,CAAE,GAAI,CACjB,KAAK,CAAE,IAAK,CACZ,SAAS,CAAE,UAAW,CACtB,OAAO,CAAE,IAAK,CACd,UAAU,CAAE,GAAI,CACjB,AAED,AAAA,2BAA2B,AAAC,CAC1B,WAAW,CAAC,GAAI,CAChB,SAAS,CAAC,IAAK,CACf,WAAW,CAAE,GAAI,CACjB,KAAK,CAAE,IAAK,CACZ,MAAM,CAAE,KAAM,CACf,AAED,AAAA,IAAI,AAAC,CACH,KAAK,CAAE,IAAK,CACZ,WAAW,CAAE,GAAI,CAClB,AAED,AAAA,kBAAkB,AAAC,CACjB,MAAM,CAAE,aAAc,CACtB,OAAO,CAAE,MAAO,CACjB,AAED,AAAyB,wBAAD,CAAC,EAAE,AAAC,CAC1B,MAAM,CAAE,KAAM,CACf,AAED,AAA2B,wBAAH,CAAC,EAAE,AAAA,QAAQ,AAAC,CAClC,OAAO,CAAE,YAAa,CACtB,OAAO,CAAE,QAAS,CAClB,aAAa,CAAE,IAAK,CAEpB,KAAK,CAAE,IAAK,CACZ,UAAU,CAAE,OAAQ,CACpB,MAAM,CAAE,iBAAkB,CAC3B,AAKD,AAAA,qBAAqB,AAAC,CACpB,OAAO,CAAE,MAAO,CAChB,KAAK,CAAE,IAAK,CACZ,MAAM,CAAE,IAAK,CACd,AAED,AAAwB,qBAAH,CAAG,GAAG,AAAC,CAC1B,gBAAgB,CAAE,IAAK,CACvB,MAAM,CAAE,IAAK,CACb,KAAK,CAAE,GAAI,CACX,OAAO,CAAE,YAAa,CACtB,YAAY,CAAE,GAAI,CAClB,iBAAiB,CAAE,sCAAuC,CAC1D,SAAS,CAAE,sCAAuC,CACnD,AAED,AAAsB,qBAAD,CAAC,mBAAmB,AAAC,CACxC,uBAAuB,CAAE,KAAM,CAC/B,eAAe,CAAE,KAAM,CACxB,AAED,AAAsB,qBAAD,CAAC,mBAAmB,AAAC,CACxC,uBAAuB,CAAE,KAAM,CAC/B,eAAe,CAAE,KAAM,CACxB,AAED,kBAAkB,CAAlB,YAAkB,CAChB,AAAA,EAAE,CAAE,AAAA,GAAG,CAAE,AAAA,IAAI,CACX,iBAAiB,CAAE,WAAM,CAE3B,AAAA,GAAG,CACD,iBAAiB,CAAE,SAAM,EAI7B,UAAU,CAAV,YAAU,CACR,AAAA,EAAE,CAAE,AAAA,GAAG,CAAE,AAAA,IAAI,CACX,SAAS,CAAE,WAAM,CACjB,iBAAiB,CAAE,WAAM,CAE3B,AAAA,GAAG,CACD,SAAS,CAAE,SAAM,CACjB,iBAAiB,CAAE,SAAM,ElFjE7B,AAAK,KAAA,AAAA,QAAQ,AAAC,CACV,UAAU,CAAE,MAAO,CACtB,AAGD,AAAW,UAAD,CAAC,GAAG,CACd,AAAW,UAAD,CAAC,MAAM,CACjB,AAAW,UAAD,CAAC,GAAG,AAAC,CACX,SAAS,CAAE,IAAK,CACnB,AACD,AAAW,UAAD,CAAC,EAAE,AAAC,CACV,SAAS,CAAE,OAAQ,CACnB,WAAW,CAAE,GAAI,CACjB,cAAc,CAAE,kBAAmB,CACtC,AACD,AAAiB,UAAP,CAAC,EAAE,CAAG,CAAC,AAAA,aAAa,AAAC,CAC3B,aAAa,CAAE,CAAE,CACpB,AAID,AAAA,MAAM,AAAC,CACH,YAAY,CAAE,CAAE,CAChB,MAAM,CAAE,KAAM,CACd,UAAU,CAAE,IAAK,CACjB,UAAU,CAAE,MAAO,CACnB,KAAK,CAAE,IAAK,CACf,AACD,AAAM,MAAA,AAAA,MAAM,CACZ,AAAM,MAAA,AAAA,OAAO,AAAC,CACV,OAAO,CAAE,GAAI,CACb,OAAO,CAAE,KAAM,CAClB,AACD,AAAM,MAAA,AAAA,MAAM,AAAC,CACT,KAAK,CAAE,IAAK,CACf,AACD,AAAO,MAAD,CAAC,EAAE,AAAC,CACN,OAAO,CAAE,MAAO,CACnB,AACD,AAAU,MAAJ,CAAC,EAAE,CAAC,CAAC,AAAC,CACR,OAAO,CAAE,YAAa,CACtB,OAAO,CAAE,QAAS,CAClB,gBAAgB,CAAE,IAAK,CACvB,MAAM,CAAE,cAAe,CACvB,aAAa,CAAE,IAAK,CACpB,UAAU,CAAE,mBAAoB,CACnC,AACD,AAAW,MAAL,CAAC,EAAE,CAAC,CAAC,AAAA,MAAM,CACjB,AAAW,MAAL,CAAC,EAAE,CAAC,CAAC,AAAA,MAAM,AAAC,CACd,eAAe,CAAE,IAAK,CACtB,YAAY,CAAE,OAAQ,CACzB,AACD,AAAa,YAAD,CAAC,CAAC,AAAC,CACX,KAAK,CAAE,KACV,CAAC,AACF,AAAa,YAAD,CAAC,CAAC,AAAC,CACX,KAAK,CAAE,IACV,CAAC", - "names": [] -} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["../../../src/scss/main.scss","../../../src/bower_components/normalize.css/_normalize.scss","../../../src/bower_components/foundation-sites/scss/grid/_classes.scss","../../../src/bower_components/foundation-sites/scss/grid/_row.scss","../../../src/scss/_settings.scss","../../../src/bower_components/foundation-sites/scss/util/_mixins.scss","../../../src/bower_components/foundation-sites/scss/grid/_gutter.scss","../../../src/bower_components/foundation-sites/scss/util/_breakpoint.scss","../../../src/bower_components/foundation-sites/scss/grid/_size.scss","../../../src/bower_components/foundation-sites/scss/grid/_column.scss","../../../src/bower_components/foundation-sites/scss/_global.scss","../../../src/bower_components/foundation-sites/scss/grid/_position.scss","../../../src/bower_components/foundation-sites/scss/grid/_layout.scss","../../../src/scss/_helpers.scss","../../../src/scss/_lazyload.scss","../../../src/scss/_forms.scss","../../../src/scss/_template.scss","../../../src/scss/_pageheader.scss","../../../src/scss/_pagecontent.scss","../../../src/scss/_sidebar.scss","../../../src/scss/_daux.scss","../../../src/scss/_highlight.scss","../../../src/scss/_tipuesearch.scss"],"names":[],"mappings":"AAEA,cACI,mBCHJ,4EAYA,KACE,uBACA,iBACA,0BACA,8BAUF,KACE,SAOF,wCAME,cAQF,GACE,cACA,eAWF,uBAGE,cAOF,OACE,gBAQF,GACE,uBACA,SACA,iBAQF,IACE,gCACA,cAWF,EACE,+BACA,qCAQF,iBAEE,gBAQF,YACE,mBACA,0BACA,iCAOF,SAEE,oBAOF,SAEE,mBAQF,cAGE,gCACA,cAOF,IACE,kBAOF,KACE,sBACA,WAOF,MACE,cAQF,QAEE,cACA,cACA,kBACA,wBAGF,IACE,eAGF,IACE,WAUF,YAEE,qBAOF,sBACE,aACA,SAOF,IACE,kBAOF,eACE,gBAWF,sCAKE,uBACA,eACA,iBACA,SAQF,aAEE,iBAQF,cAEE,oBASF,qDAIE,0BAOF,wHAIE,kBACA,UAOF,4GAIE,8BAOF,SACE,wBACA,aACA,2BAUF,OACE,sBACA,cACA,cACA,eACA,UACA,mBAQF,SACE,qBACA,wBAOF,SACE,cAQF,6BAEE,sBACA,UAOF,kFAEE,YAQF,cACE,6BACA,oBAOF,qFAEE,wBAQF,6BACE,0BACA,aAWF,aAEE,cAOF,QACE,kBAUF,OACE,qBAOF,SACE,aAUF,SACE,aClbA,KCoCE,UCdW,SDeX,iBACA,kBE8EF,yBAEE,YACA,cAOF,YACE,WH1HE,6CIpBJ,eACA,gBJyBE,UCqDE,YAHO,UAIP,aAJO,UI6DT,oCL/GA,UCqDE,YAHO,WAIP,aAJO,YD/CP,mBACE,cACA,eAKJ,cACE,eAEA,mBACE,iBACA,kBAMN,iBM3CA,WC8CA,MCyCY,KDjCN,aAHQ,QAIR,cAJQ,QFkFZ,oCL1FF,iBOWM,aAHQ,SAIR,cAJQ,UAgBZ,2EACE,MCoBS,MCtDb,qEACE,MDoDU,KRhCZ,iCACE,WAIF,2CACE,eACA,gBACA,cACA,eAME,SMtEJ,oBN4EM,cS3EJ,kBACA,KAHS,cTiFL,cS/EJ,kBACA,KAHS,eTyFP,gBS5DJ,eT0CI,SMtEJ,qBN4EM,cS3EJ,kBACA,KAHS,eTiFL,cS/EJ,kBACA,KAHS,gBTyFP,gBS5DJ,0BT0CI,SMtEJ,UN4EM,cS3EJ,kBACA,KAHS,ITiFL,cS/EJ,kBACA,KAHS,KTyFP,gBS5DJ,2BT0CI,SMtEJ,qBN4EM,cS3EJ,kBACA,KAHS,eTiFL,cS/EJ,kBACA,KAHS,gBTyFP,gBS5DJ,gBT0CI,SMtEJ,qBN4EM,cS3EJ,kBACA,KAHS,eTiFL,cS/EJ,kBACA,KAHS,gBTyFP,gBS5DJ,2BT0CI,SMtEJ,UN4EM,cS3EJ,kBACA,KAHS,ITiFL,cS/EJ,kBACA,KAHS,KTyFP,gBS5DJ,2BT0CI,SMtEJ,qBN4EM,cS3EJ,kBACA,KAHS,eTiFL,cS/EJ,kBACA,KAHS,gBTyFP,gBS5DJ,gBT0CI,SMtEJ,qBN4EM,cS3EJ,kBACA,KAHS,eTiFL,cS/EJ,kBACA,KAHS,gBTyFP,gBS5DJ,2BT0CI,SMtEJ,UN4EM,cS3EJ,kBACA,KAHS,ITiFL,cS/EJ,kBACA,KAHS,KTyFP,gBS5DJ,2BT0CI,UMtEJ,qBN4EM,eS3EJ,kBACA,KAHS,eTiFL,eS/EJ,kBACA,KAHS,gBTyFP,gBS5DJ,gBT0CI,UMtEJ,qBN4EM,eS3EJ,kBACA,KAHS,eTiFL,eS/EJ,kBACA,KAHS,gBTyFP,iBS5DJ,2BT0CI,UMtEJ,WNwFI,iBS5DJ,2BCrBA,yCACE,WACA,MF8EU,KExDV,yEACE,WAGF,6EACE,WAGF,+DACE,MF+CQ,KEhFZ,yCACE,UACA,MF8EU,KExDV,yEACE,WAGF,6EACE,WAGF,+DACE,MF+CQ,KEhFZ,yCACE,qBACA,MF8EU,KExDV,yEACE,WAGF,6EACE,WAGF,+DACE,MF+CQ,KEhFZ,yCACE,UACA,MF8EU,KExDV,yEACE,WAGF,6EACE,WAGF,+DACE,MF+CQ,KEhFZ,yCACE,UACA,MF8EU,KExDV,yEACE,WAGF,6EACE,WAGF,+DACE,MF+CQ,KEhFZ,yCACE,qBACA,MF8EU,KExDV,yEACE,WAGF,6EACE,WAGF,+DACE,MF+CQ,KEhFZ,yCACE,qBACA,MF8EU,KExDV,yEACE,WAGF,6EACE,WAGF,+DACE,MF+CQ,KEhFZ,yCACE,YACA,MF8EU,KExDV,yEACE,WAGF,6EACE,WAGF,+DACE,MF+CQ,KReR,iDI1GJ,eACA,gBJ2GI,qBACE,cACA,eAIJ,kCACE,cACA,eAMA,qDIjHJ,aADS,QAET,cAFS,QJsHP,gBSjHA,iBACA,kBALA,6DACE,WACA,WTwHF,8CS5GF,gBACA,cACA,eACA,WJ+GE,oCL/DE,UMtEJ,oBN4EM,eS3EJ,kBACA,KAHS,cTiFL,eS/EJ,kBACA,KAHS,eTyFP,iBS5DJ,eT0CI,UMtEJ,qBN4EM,eS3EJ,kBACA,KAHS,eTiFL,eS/EJ,kBACA,KAHS,gBTyFP,iBS5DJ,0BT0CI,UMtEJ,UN4EM,eS3EJ,kBACA,KAHS,ITiFL,eS/EJ,kBACA,KAHS,KTyFP,iBS5DJ,2BT0CI,UMtEJ,qBN4EM,eS3EJ,kBACA,KAHS,eTiFL,eS/EJ,kBACA,KAHS,gBTyFP,iBS5DJ,gBT0CI,UMtEJ,qBN4EM,eS3EJ,kBACA,KAHS,eTiFL,eS/EJ,kBACA,KAHS,gBTyFP,iBS5DJ,2BT0CI,UMtEJ,UN4EM,eS3EJ,kBACA,KAHS,ITiFL,eS/EJ,kBACA,KAHS,KTyFP,iBS5DJ,2BT0CI,UMtEJ,qBN4EM,eS3EJ,kBACA,KAHS,eTiFL,eS/EJ,kBACA,KAHS,gBTyFP,iBS5DJ,gBT0CI,UMtEJ,qBN4EM,eS3EJ,kBACA,KAHS,eTiFL,eS/EJ,kBACA,KAHS,gBTyFP,iBS5DJ,2BT0CI,UMtEJ,UN4EM,eS3EJ,kBACA,KAHS,ITiFL,eS/EJ,kBACA,KAHS,KTyFP,iBS5DJ,2BT0CI,WMtEJ,qBN4EM,gBS3EJ,kBACA,KAHS,eTiFL,gBS/EJ,kBACA,KAHS,gBTyFP,iBS5DJ,gBT0CI,WMtEJ,qBN4EM,gBS3EJ,kBACA,KAHS,eTiFL,gBS/EJ,kBACA,KAHS,gBTyFP,kBS5DJ,2BT0CI,WMtEJ,WNwFI,kBS5DJ,2BCrBA,2CACE,WACA,MF8EU,KExDV,2EACE,WAGF,+EACE,WAGF,iEACE,MF+CQ,KEhFZ,2CACE,UACA,MF8EU,KExDV,2EACE,WAGF,+EACE,WAGF,iEACE,MF+CQ,KEhFZ,2CACE,qBACA,MF8EU,KExDV,2EACE,WAGF,+EACE,WAGF,iEACE,MF+CQ,KEhFZ,2CACE,UACA,MF8EU,KExDV,2EACE,WAGF,+EACE,WAGF,iEACE,MF+CQ,KEhFZ,2CACE,UACA,MF8EU,KExDV,2EACE,WAGF,+EACE,WAGF,iEACE,MF+CQ,KEhFZ,2CACE,qBACA,MF8EU,KExDV,2EACE,WAGF,+EACE,WAGF,iEACE,MF+CQ,KEhFZ,2CACE,qBACA,MF8EU,KExDV,2EACE,WAGF,+EACE,WAGF,iEACE,MF+CQ,KEhFZ,2CACE,YACA,MF8EU,KExDV,2EACE,WAGF,+EACE,WAGF,iEACE,MF+CQ,KReR,mDI1GJ,eACA,gBJ2GI,sBACE,cACA,eAIJ,mCACE,cACA,eAMA,uDIjHJ,aADS,SAET,cAFS,SJsHP,iBSjHA,iBACA,kBALA,+DACE,WACA,WTwHF,iDS5GF,gBACA,cACA,eACA,YJ+GE,oCL/DE,SMtEJ,oBN4EM,cS3EJ,kBACA,KAHS,cTiFL,cS/EJ,kBACA,KAHS,eTyFP,gBS5DJ,eT0CI,SMtEJ,qBN4EM,cS3EJ,kBACA,KAHS,eTiFL,cS/EJ,kBACA,KAHS,gBTyFP,gBS5DJ,0BT0CI,SMtEJ,UN4EM,cS3EJ,kBACA,KAHS,ITiFL,cS/EJ,kBACA,KAHS,KTyFP,gBS5DJ,2BT0CI,SMtEJ,qBN4EM,cS3EJ,kBACA,KAHS,eTiFL,cS/EJ,kBACA,KAHS,gBTyFP,gBS5DJ,gBT0CI,SMtEJ,qBN4EM,cS3EJ,kBACA,KAHS,eTiFL,cS/EJ,kBACA,KAHS,gBTyFP,gBS5DJ,2BT0CI,SMtEJ,UN4EM,cS3EJ,kBACA,KAHS,ITiFL,cS/EJ,kBACA,KAHS,KTyFP,gBS5DJ,2BT0CI,SMtEJ,qBN4EM,cS3EJ,kBACA,KAHS,eTiFL,cS/EJ,kBACA,KAHS,gBTyFP,gBS5DJ,gBT0CI,SMtEJ,qBN4EM,cS3EJ,kBACA,KAHS,eTiFL,cS/EJ,kBACA,KAHS,gBTyFP,gBS5DJ,2BT0CI,SMtEJ,UN4EM,cS3EJ,kBACA,KAHS,ITiFL,cS/EJ,kBACA,KAHS,KTyFP,gBS5DJ,2BT0CI,UMtEJ,qBN4EM,eS3EJ,kBACA,KAHS,eTiFL,eS/EJ,kBACA,KAHS,gBTyFP,gBS5DJ,gBT0CI,UMtEJ,qBN4EM,eS3EJ,kBACA,KAHS,eTiFL,eS/EJ,kBACA,KAHS,gBTyFP,iBS5DJ,2BT0CI,UMtE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","file":"main.css"} \ No newline at end of file diff --git a/themes/modmore/templates/content.php b/themes/modmore/templates/content.php index bcd5d79b..35f764cb 100644 --- a/themes/modmore/templates/content.php +++ b/themes/modmore/templates/content.php @@ -32,4 +32,4 @@ or report an issue. Thank you!

    - \ No newline at end of file + diff --git a/themes/modmore/templates/layout/00_layout.php b/themes/modmore/templates/layout/00_layout.php index abec502f..640afdeb 100644 --- a/themes/modmore/templates/layout/00_layout.php +++ b/themes/modmore/templates/layout/00_layout.php @@ -20,50 +20,30 @@ + + + + - "; - } ?> + getTheme()->getFonts() as $font) { ?> + + - "; - } ?> - - - - - + getTheme()->getCSS() as $css) { ?> + + - + section('content'); ?> - - -'; -} ?> - - - - - - - - +getTheme()->getJS() as $js) { ?> + + -} ?> +insert('theme::partials/search_script', ['page' => $page, 'base_url' => $base_url]); ?> - - + diff --git a/themes/modmore/templates/layout/05_page.php b/themes/modmore/templates/layout/05_page.php index a649f6e1..c621da51 100644 --- a/themes/modmore/templates/layout/05_page.php +++ b/themes/modmore/templates/layout/05_page.php @@ -18,6 +18,35 @@