commit 1f72193a64ee2203a0e62e8e8359f1a70ecc927e Author: avives Date: Fri Aug 21 19:29:00 2026 -0600 feat: VivesPOS landing on Winter CMS 1.2 — theme + plugin + Dockerfile - Base: wintercms/winter branch 1.2 (full framework) - Theme vivespos: Canvas 7 + Bootstrap 5 CDN, custom CSS - Layout: deferred GTM/GA4 tracking, JSON-LD SoftwareApplication - Partials: hero (offline-first), features, modes (offline/nube toggle), screenshots, pricing (3 planes), comparison, FAQ, CTA - Plugin VivesPOS.Site with ContactForm - Dockerfile: PHP 8.2 Apache, port 80, healthcheck - Added winter/wn-pages, blog, sitemap, seo plugins - Active theme set to vivespos diff --git a/.devcontainer/.vscode/launch.json b/.devcontainer/.vscode/launch.json new file mode 100644 index 0000000..f855a76 --- /dev/null +++ b/.devcontainer/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Listen for Xdebug", + "type": "php", + "request": "launch", + "port": 9003 + }, + ] +} diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 0000000..eeea50d --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1,72 @@ +# Welcome to the Winter development environment + +

+ Winter CMS Logo +

+ +This development environment container sets up a fully-functional installation of Winter CMS, built on [FrankenPHP](https://frankenphp.dev/) with PHP 8.4. It makes it simple to start working with Winter CMS in VSCode, PHPStorm and online code-editing suites such as GitHub Codespaces. + +This image is based on the official [Winter CMS Docker image](https://github.com/wintercms/docker) and inherits all its features. For detailed configuration options, see the [Docker image README](https://github.com/wintercms/docker/blob/main/README.md). + +If you opted to use the `bootstrap-winter` feature, which is enabled by default, Winter CMS will be automatically configured and an administrator account will be generated with the credentials **admin / admin** for you to quickly sign in. It is recommended once you have done so that you change this password immediately. + +The following plugins and themes will be installed automatically with this feature: + +- Workshop theme (https://github.com/wintercms/wn-workshop-theme) +- Pages plugin (https://github.com/wintercms/wn-pages-plugin) +- Blog plugin (https://github.com/wintercms/wn-blog-plugin) +- Test plugin (https://github.com/wintercms/wn-test-plugin) + +## Using this environment + +When this environment is built, FrankenPHP is automatically started, with the root folder of the Winter project being used. A preview of the website will be opened immediately - if you do not see this, you can open the **Ports** tab in VSCode to view the URL generated for viewing the project. + +XDebug is enabled by default, and allows you to quickly use step debugging. It will be available in the **Debug** tab of VSCode or similar screen in other IDEs. + +By default, when using the `bootstrap-winter` feature, changes to certain folders and locations will be ignored by Git to keep the change list clean. This includes the `plugins` and `themes` folders, the `config/app.php` file and the `composer.json` file in the root folder. If you wish to use this environment for your own projects, it is recommended that you do not use this feature. Please see the **Using in your own projects** section below for using this environment outside of Winter development. + +## Environment platform + +The following software is installed in this environment. + +- FrankenPHP (Caddy) +- PHP 8.4 with the following extensions: + - `intl` + - `gd` + - `xdebug` +- Composer +- NodeJS 24 (including `npm`) +- Git + +## Using in your own projects + +You may use this development environment for your own projects, making it a great starting point to hit the ground running with Winter. It is recommended that you *disable* the `bootstrap-winter` feature when using this environment for your own projects. + +You may disable this feature by modifying the `.devcontainer/devcontainer.json` file before running the container and commenting out the feature: + +```json5 + "features": { + "ghcr.io/devcontainers/features/common-utils:2": {}, + "ghcr.io/devcontainers/features/github-cli:1": {}, + // Comment the following feature if you wish to bootstrap and configure Winter manually (ie. you wish to use this for your own project) + "./local-features/bootstrap-winter": "latest" + }, +``` + +If this feature is disabled, you must bootstrap your project manually. This includes: + +- Downloading the Composer dependencies. +- Generating the configuration for the project, either as an `.env` file or in the `config` folder. +- Finally, Running the database migrations. + +You may view the `.devcontainer/local-features/bootstrap-winter/bootstrap.sh` file to see how we bootstrap Winter, and run these commands manually. You will only need to do this once per project container. + +If you wish to mount your own volumes, use your own databases or any other complex usages, please review the [Winter Docker image documentation](https://github.com/wintercms/docker/blob/main/README.md#persisting-data) or the [FrankenPHP environment variables](https://frankenphp.dev/docs/config/#environment-variables) for configuration options. + +## Troubleshooting + +### Preview website missing styles / assets on Codespaces + +By default, ports that are forwarded in Codespaces are private by default. While we have tried to fix this automatically in the Winter bootstrap process by making the port public through the GitHub CLI, it unfortunately is not consistently applied. + +If you find that your preview website is missing assets or styling, open the **Ports** tab by opening the Action Palette in Codespaces (`F1`) and using the **View: Toggle Ports** action. Right click on the **Preview Winter installation** port, right click on it and choose **Port Visiblity -> Public**. This should resolve the issue. diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..6428060 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,60 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/debian +{ + "name": "Winter on PHP 8.4", + "image": "ghcr.io/wintercms/winter:latest", + "features": { + "ghcr.io/devcontainers/features/common-utils:2": { + "installZsh": true, + "configureZshAsDefaultShell": true, + "username": "winter", + "upgradePackages": false + }, + "ghcr.io/devcontainers/features/github-cli:1": {}, + // Comment the following feature if you wish to bootstrap and configure Winter manually (ie. you wish to use this for your own project) + "./local-features/bootstrap-winter": "latest" + }, + "workspaceMount": "source=${localWorkspaceFolder},target=/winter,type=bind", + "workspaceFolder": "/winter", + "containerEnv": { + "APP_DEBUG": "true", + "XDEBUG_MODE": "debug", + "ROUTES_CACHE": "false", + "ASSET_CACHE": "false", + "DB_CONNECTION": "sqlite", + "DB_DATABASE": "${containerWorkspaceFolder}/storage/database.sqlite" + }, + "forwardPorts": [8000], + "portsAttributes": { + "8000": { + "label": "Preview Winter installation", + "onAutoForward": "openPreview" + }, + "9003": { + "label": "Xdebug", + "onAutoForward": "notify" + } + }, + "customizations": { + "vscode": { + "settings": { + "php.validate.executablePath": "/usr/local/bin/php", + "phpcs.executablePath": "${containerWorkspaceFolder}/vendor/bin/phpcs" + }, + "extensions": [ + "xdebug.php-debug", + "bmewburn.vscode-intelephense-client", + "shevaua.phpcs", + "swordev.phpstan", + "wintercms.winter-cms" + ] + }, + "codespaces": { + "openFiles": [ + ".devcontainer/README.md" + ] + } + }, + "postAttachCommand": "nohup ${containerWorkspaceFolder}/.devcontainer/run-frankenphp.sh > /dev/null 2>&1", + "remoteUser": "winter" +} diff --git a/.devcontainer/local-features/bootstrap-winter/bootstrap.sh b/.devcontainer/local-features/bootstrap-winter/bootstrap.sh new file mode 100755 index 0000000..31a65a8 --- /dev/null +++ b/.devcontainer/local-features/bootstrap-winter/bootstrap.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +set -e + +if [ ! -d "${PWD}/vendor" ] && [ ! -f "${PWD}/composer.lock" ]; then + echo "### Updating Composer dependencies" + php ${PWD}/.devcontainer/local-features/bootstrap-winter/update-composer.php + composer update --no-interaction --no-scripts --no-audit +fi + +if [ ! -f "${PWD}/.env" ]; then + echo "### Generating .env file" + php artisan winter:env -q + php artisan key:generate -q +fi + +if [ "${DB_CONNECTION}" = "sqlite" ] && [ "${DB_DATABASE}" = "${PWD}/storage/database.sqlite" ] && [ ! -f "${PWD}/storage/database.sqlite" ]; then + SETUP_ADMIN=true + echo "### Creating SQLite database" + touch storage/database.sqlite +fi + +echo "### Run migrations" +php artisan migrate + +echo "### Set theme" +php artisan theme:use workshop + +if [ "${SETUP_ADMIN}" = true ]; then + echo "### Setup admin" + php artisan winter:passwd admin admin +fi + +echo "### Ignoring files in Git" +echo "plugins/*" >> "${PWD}/.git/info/exclude" +echo "themes/*" >> "${PWD}/.git/info/exclude" +echo "composer.json" >> "${PWD}/.git/info/exclude" +git update-index --assume-unchanged composer.json +git restore config + +cp ${PWD}/.devcontainer/.vscode/launch.json ${PWD}/.vscode/launch.json + +echo "### Mirror site to public directory" +php artisan winter:mirror public + +if [ "${CODESPACES}" = "true" ]; then + echo "### Configure for Codespaces" + php ${PWD}/.devcontainer/local-features/bootstrap-winter/codespaces.php + git update-index --assume-unchanged config/app.php + gh codespace ports visibility 8000:public -c $CODESPACE_NAME +fi diff --git a/.devcontainer/local-features/bootstrap-winter/codespaces.php b/.devcontainer/local-features/bootstrap-winter/codespaces.php new file mode 100644 index 0000000..2c7ea56 --- /dev/null +++ b/.devcontainer/local-features/bootstrap-winter/codespaces.php @@ -0,0 +1,25 @@ +set('trustedHosts', [ + 'localhost', + '^(.+\.)?app.github.dev', +]); +$config->set('trustedProxies', '*'); + +$config->write(); + +$env = EnvFile::open($root . '/.env'); + +$env->set('APP_URL', 'https://' . $_ENV['CODESPACE_NAME'] . '.app.github.dev'); +$env->set('LINK_POLICY', 'force'); + +$env->write(); diff --git a/.devcontainer/local-features/bootstrap-winter/devcontainer-feature.json b/.devcontainer/local-features/bootstrap-winter/devcontainer-feature.json new file mode 100644 index 0000000..a9d74f2 --- /dev/null +++ b/.devcontainer/local-features/bootstrap-winter/devcontainer-feature.json @@ -0,0 +1,6 @@ +{ + "id": "bootstrap-winter", + "name": "Bootstrap Winter", + "description": "Bootstrap and configure Winter CMS automatically for development on Winter itself", + "postCreateCommand": "sh ./.devcontainer/local-features/bootstrap-winter/bootstrap.sh" +} diff --git a/.devcontainer/local-features/bootstrap-winter/install.sh b/.devcontainer/local-features/bootstrap-winter/install.sh new file mode 100755 index 0000000..262318b --- /dev/null +++ b/.devcontainer/local-features/bootstrap-winter/install.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +# Install Xdebug extension +install-php-extensions xdebug + +echo "Done" diff --git a/.devcontainer/local-features/bootstrap-winter/update-composer.php b/.devcontainer/local-features/bootstrap-winter/update-composer.php new file mode 100644 index 0000000..fbd1d8f --- /dev/null +++ b/.devcontainer/local-features/bootstrap-winter/update-composer.php @@ -0,0 +1,27 @@ + 'dev-main', + 'winter/wn-blog-plugin' => 'dev-main', + 'winter/wn-blog-plugin' => 'dev-main', + 'winter/wn-workshop-theme' => 'dev-main', +]; + +// Install Winter packages +foreach ($packages as $package => $version) { + if (!in_array($package, array_keys($composer['require']))) { + $composer['require'][$package] = $version; + } +} + +// Change Merge plugin config +$composer['extra']['merge-plugin']['include'] = [ + 'plugins/*/*/composer.json', +]; + +file_put_contents( + $composerPath, + json_encode($composer, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) +); diff --git a/.devcontainer/run-frankenphp.sh b/.devcontainer/run-frankenphp.sh new file mode 100755 index 0000000..79e7106 --- /dev/null +++ b/.devcontainer/run-frankenphp.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +set -e + +USER_ID=$(id -u) +GROUP_ID=$(id -g) + +# Ensure the Caddy config and data directories are owned by the current user +sudo chown -R $USER_ID:$GROUP_ID /config/caddy +sudo chown -R $USER_ID:$GROUP_ID /data +sudo touch /var/log/frankenphp.log +sudo chown $USER_ID:$GROUP_ID /var/log/frankenphp.log + +# If debugging is enabled, disable Opcache so changes are reflected immediately +if [ "${APP_DEBUG}" = "true" ] || [ "${APP_DEBUG}" = "1" ]; then + sudo sed -i 's/opcache.enable = On/opcache.enable = Off/' /usr/local/etc/php/conf.d/winter.ini +fi + +# Run server in background +if [ "${CODESPACES}" = "true" ]; then + # Ensure environment variables are set correctly for Codespaces + SERVER_NAME="http://:8000" APP_URL="https://${CODESPACE_NAME}-8000.app.github.dev" /usr/local/bin/frankenphp run -c /etc/frankenphp/Caddyfile -a caddyfile > /var/log/frankenphp.log 2>&1 & +else + /usr/local/bin/frankenphp run -c /etc/frankenphp/Caddyfile -a caddyfile > /var/log/frankenphp.log 2>&1 & +fi + diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..39f90e5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 4 + +[**/.github/workflows/**.{yml,yaml}] +indent_size = 2 diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..f2ea1a4 --- /dev/null +++ b/.env.example @@ -0,0 +1,13 @@ +APP_ENV=production +APP_DEBUG=false +APP_KEY= +APP_URL=http://localhost + +DB_CONNECTION=sqlite +DB_DATABASE=storage/database.sqlite + +CACHE_STORE=file +SESSION_DRIVER=file +QUEUE_CONNECTION=sync + +MAIL_MAILER=log diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1a7fadf --- /dev/null +++ b/.gitattributes @@ -0,0 +1,10 @@ +* text=auto + +*.md diff=markdown +*.php diff=php + +/.devcontainer export-ignore +/.github export-ignore +.gitattributes export-ignore +CHANGELOG.md export-ignore +/package.json export-ignore diff --git a/.github/ISSUE_TEMPLATE/1_BUG_REPORT.yaml b/.github/ISSUE_TEMPLATE/1_BUG_REPORT.yaml new file mode 100644 index 0000000..4ff78ea --- /dev/null +++ b/.github/ISSUE_TEMPLATE/1_BUG_REPORT.yaml @@ -0,0 +1,78 @@ +name: Bug Report +description: Report a general Winter CMS or Storm library issue. See our policy below if reporting a security issue. +labels: ["Status: Review Needed", "Type: Unconfirmed Bug"] +body: + - type: markdown + attributes: + value: | + Thanks for your interest in improving Winter CMS! To avoid duplicate issues please ensure that no previous issues already cover the problem you wish to report before you submit your report. Otherwise, feel free to fill out the form below to submit an issue. + + **Please do not use this form to report a security issue. For security issues, review our [Security Policy](https://github.com/wintercms/winter/security/policy).** + - type: dropdown + id: build + attributes: + label: Winter CMS Build + description: Please select the Winter CMS build that you encountered your issue with. You can find the version in the **Updates & Plugins** section of the Settings page of the Backend, or by running the `php artisan winter:version` command. + options: + - dev-develop + - 1.2 + - 1.1 + - 1.0 (please try updating first) + - Other (please specify below) + validations: + required: true + - type: dropdown + id: php_version + attributes: + label: PHP Version + description: Please provide us the branch of PHP version. For example, for PHP version 7.4.9, select `7.4`, or for PHP version 8.0.1, select `8.0`. + options: + - 8.4 + - 8.3 + - 8.2 + - 8.1 + - 8.0 + - 7.4 + - 7.3 + - 7.2 + - Other (please specify below) + validations: + required: true + - type: dropdown + id: database + attributes: + label: Database engine + description: Please provide us with the database server type you are running. + options: + - MySQL/MariaDB + - PostgreSQL + - SQLite + - SQL Server + - No database + - Other (please specify below) + validations: + required: true + - type: input + id: plugins + attributes: + label: Plugins installed + description: If any plugins are installed, please list them here in the format `Author.PluginName, Author2.PluginName, etc`. + - type: textarea + id: description + attributes: + label: Issue description + description: Please describe the issue in as much detail as possible. Include screenshots of error messages or copy and paste any logs that result from the issue occurring. + validations: + required: true + - type: textarea + id: replication + attributes: + label: Steps to replicate + description: Please list the steps that you took in order for the issue to occur. + validations: + required: true + - type: textarea + id: workaround + attributes: + label: Workaround + description: If you have a workaround, please detail it here, for the benefit of other users who encounter the issue. diff --git a/.github/ISSUE_TEMPLATE/2_PRE_PR.yaml b/.github/ISSUE_TEMPLATE/2_PRE_PR.yaml new file mode 100644 index 0000000..523633f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/2_PRE_PR.yaml @@ -0,0 +1,32 @@ +name: Pre-Pull Request Discussion +description: If you intend to submit a PR and wish to discuss it first, start here. +labels: ["Status: Review Needed", "Type: Conceptual Enhancement"] +body: + - type: markdown + attributes: + value: | + Thanks for your interest in submitting a pull request to Winter CMS. We always value contributions from our community. If you wish to start a discussion on the pull request before submission, such as discussing implementation details, please use this form. + - type: dropdown + id: subsystem + attributes: + label: Package targeted + description: Please select which portion of Winter CMS your PR is targeting. + options: + - Winter CMS + - Storm Library + - Both + - Other (please specify below) + validations: + required: true + - type: textarea + id: description + attributes: + label: Description + description: Please describe what your PR is intending to do. + validations: + required: true + - type: textarea + id: compatibility + attributes: + label: Will this change be backwards-compatible? + description: Please describe if this intended change may break backwards compatibility or not. If it does, state the rationale in which you believe this to be an acceptable break in backwards compatibility. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..3d872e1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,14 @@ +blank_issues_enabled: true +contact_links: + - name: General Winter CMS Support + url: https://wintercms.com/support + about: If you need help with Winter CMS, please review our support options. + - name: Discord + url: https://discord.gg/D5MFSPH6Ux + about: Join us on Discord for general discussions and one-on-one help. + - name: Feature Requests + url: https://github.com/wintercms/winter/discussions + about: Please post an Idea thread to the Discussions section for feature requests. + - name: Documentation Issue + url: https://github.com/wintercms/docs + about: For documentation issues, please submit an issue or PR to the Docs repository. diff --git a/.github/assets/Github Banner.png b/.github/assets/Github Banner.png new file mode 100644 index 0000000..aedade0 Binary files /dev/null and b/.github/assets/Github Banner.png differ diff --git a/.github/assets/sponsor-route4me.png b/.github/assets/sponsor-route4me.png new file mode 100644 index 0000000..58e0caf Binary files /dev/null and b/.github/assets/sponsor-route4me.png differ diff --git a/.github/workflows/code-quality.yaml b/.github/workflows/code-quality.yaml new file mode 100644 index 0000000..1147541 --- /dev/null +++ b/.github/workflows/code-quality.yaml @@ -0,0 +1,68 @@ +name: Code Quality + +on: + pull_request: + push: + branches: + - 1.0 + - 1.1 + - 1.2 + - develop + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + codeQuality: + runs-on: ubuntu-latest + name: PHP + steps: + - name: Checkout changes + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Install PHP and PHP Code Sniffer + uses: shivammathur/setup-php@v2 + with: + php-version: 8.2 + extensions: curl, fileinfo, gd, mbstring, openssl, pdo, pdo_sqlite, sqlite3, xml, zip + tools: phpcs + + - name: Run code quality checks (on push) + if: github.event_name == 'push' + run: ./.github/workflows/utilities/phpcs-push ${{ github.sha }} + + - name: Run code quality checks (on pull request) + if: github.event_name == 'pull_request' + run: ./.github/workflows/utilities/phpcs-pr ${{ github.base_ref }} + codeQualityJS: + runs-on: ubuntu-latest + name: JavaScript + steps: + - name: Checkout changes + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Install Node + uses: actions/setup-node@v1 + with: + node-version: 12 + + - name: Install Node dependencies for System Module + working-directory: ./modules/system + run: npm install + + - name: Run code quality checks on System Module + working-directory: ./modules/system + run: npx eslint . + + - name: Install Node dependencies for Backend Module + working-directory: ./modules/backend + run: npm install + + - name: Run code quality checks on Backend Module + working-directory: ./modules/backend + run: npx eslint . diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..50154e9 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,128 @@ +name: Docker + +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+" + +concurrency: + group: docker-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + updateDockerImage: + name: Update Docker image + runs-on: ubuntu-latest + env: + version: ${{ github.ref_name }} + steps: + - name: Checkout changes + uses: actions/checkout@v4 + with: + repository: wintercms/docker + ref: main + token: ${{ secrets.WINTER_BOT_TOKEN }} + + - name: Determine latest FrankenPHP, PHP and Node versions + id: versions + env: + GH_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + + # Stay within the major versions currently used by the Dockerfile + frankenphpMajor=$(sed -n 's/^ARG FRANKENPHP_VERSION="\([0-9]*\)\..*"$/\1/p' Dockerfile) + phpMajor=$(sed -n 's/^ARG PHP_VERSION="\([0-9]*\)\..*"$/\1/p' Dockerfile) + nodeMajor=$(sed -n 's/^ARG NODE_VERSION="v\([0-9]*\)\..*"$/\1/p' Dockerfile) + + # The base image is a combined FrankenPHP + PHP tag, so both versions must be resolved + # together - the latest of each individually may not exist as a published image. Walk + # back through the FrankenPHP releases until one with a Trixie image is found. + frankenphp="" + php="" + + for candidate in $(gh api "repos/php/frankenphp/releases?per_page=100" \ + --jq '.[] | select(.draft == false and .prerelease == false) | .tag_name' \ + | sed -n "s/^v\($frankenphpMajor\.[0-9]\+\.[0-9]\+\)$/\1/p"); do + php=$(curl -fsSL "https://hub.docker.com/v2/repositories/dunglas/frankenphp/tags?page_size=100&name=$candidate-php$phpMajor" \ + | jq -r '.results[].name' \ + | sed -n "s/^$candidate-php\($phpMajor\.[0-9]\+\.[0-9]\+\)-trixie$/\1/p" \ + | sort -V \ + | tail -n 1) + + if [ -n "$php" ]; then + frankenphp="$candidate" + break + fi + done + + if [ -z "$frankenphp" ] || [ -z "$php" ]; then + echo "Unable to resolve a FrankenPHP $frankenphpMajor.x image for PHP $phpMajor.x" >&2 + exit 1 + fi + + node=$(curl -fsSL "https://nodejs.org/dist/index.json" \ + | jq -r --arg major "v$nodeMajor." 'map(select(.version | startswith($major))) | .[0].version // ""') + + if [ -z "$node" ]; then + echo "Unable to resolve a Node $nodeMajor.x release" >&2 + exit 1 + fi + + echo "frankenphp=$frankenphp" >> "$GITHUB_OUTPUT" + echo "php=$php" >> "$GITHUB_OUTPUT" + echo "node=$node" >> "$GITHUB_OUTPUT" + + - name: Update versions + env: + frankenphp: ${{ steps.versions.outputs.frankenphp }} + php: ${{ steps.versions.outputs.php }} + node: ${{ steps.versions.outputs.node }} + run: | + set -euo pipefail + + currentFrankenphp=$(sed -n 's/^ARG FRANKENPHP_VERSION="\(.*\)"$/\1/p' Dockerfile) + currentPhp=$(sed -n 's/^ARG PHP_VERSION="\(.*\)"$/\1/p' Dockerfile) + currentNode=$(sed -n 's/^ARG NODE_VERSION="\(.*\)"$/\1/p' Dockerfile) + + sed -i -E "s/^ARG WINTER_VERSION=\".*\"$/ARG WINTER_VERSION=\"$version\"/" Dockerfile + sed -i -E "s/^ARG FRANKENPHP_VERSION=\".*\"$/ARG FRANKENPHP_VERSION=\"$frankenphp\"/" Dockerfile + sed -i -E "s/^ARG PHP_VERSION=\".*\"$/ARG PHP_VERSION=\"$php\"/" Dockerfile + sed -i -E "s/^ARG NODE_VERSION=\".*\"$/ARG NODE_VERSION=\"$node\"/" Dockerfile + + grep -q "^ARG WINTER_VERSION=\"$version\"$" Dockerfile + grep -q "^ARG FRANKENPHP_VERSION=\"$frankenphp\"$" Dockerfile + grep -q "^ARG PHP_VERSION=\"$php\"$" Dockerfile + grep -q "^ARG NODE_VERSION=\"$node\"$" Dockerfile + + # Written outside the checkout so that it is not picked up by the commit + notes="$RUNNER_TEMP/release-notes.md" + echo "- Updated Winter to version $version" > "$notes" + + if [ "$currentFrankenphp" != "$frankenphp" ]; then + echo "- Updated FrankenPHP to version $frankenphp" >> "$notes" + fi + if [ "$currentPhp" != "$php" ]; then + echo "- Updated PHP to version $php" >> "$notes" + fi + if [ "$currentNode" != "$node" ]; then + echo "- Updated Node to version $node" >> "$notes" + fi + + - name: Commit changes + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: Update to Winter ${{ env.version }} + file_pattern: Dockerfile + commit_user_name: Winter Bot + commit_user_email: 80384029+WinterCMSBot@users.noreply.github.com + + - name: Publish release + env: + GH_TOKEN: ${{ secrets.WINTER_BOT_TOKEN }} + run: | + gh release create "$version" \ + --repo wintercms/docker \ + --target main \ + --title "$version" \ + --notes-file "$RUNNER_TEMP/release-notes.md" diff --git a/.github/workflows/manifest.yml b/.github/workflows/manifest.yml new file mode 100644 index 0000000..e03b53d --- /dev/null +++ b/.github/workflows/manifest.yml @@ -0,0 +1,69 @@ +name: Manifest + +on: + push: + tags: + - "*" + workflow_dispatch: + +concurrency: + group: manifest-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + updateManifest: + name: Update manifest + runs-on: ubuntu-latest + env: + phpVersion: "8.4" + extensions: curl, fileinfo, gd, mbstring, openssl, pdo, pdo_sqlite, sqlite3, xml, zip + key: winter-cms-cache-develop + steps: + - name: Checkout changes + uses: actions/checkout@v4 + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ env.phpVersion }} + extensions: ${{ env.extensions }} + + - name: Install Composer dependencies + run: composer install --no-interaction --no-progress --no-scripts + + - name: Download manifest + run: wget -O builds.json https://github.com/wintercms/meta/raw/master/manifest/builds.json + + - name: Run manifest + run: php artisan winter:manifest builds.json + + - name: Create artifact + uses: actions/upload-artifact@v4 + with: + name: winter-manifest + path: builds.json + + commitManifest: + name: Commit manifest + runs-on: ubuntu-latest + needs: updateManifest + steps: + - name: Checkout changes + uses: actions/checkout@v4 + with: + repository: wintercms/meta + ref: master + token: ${{ secrets.WINTER_BOT_TOKEN }} + + - name: Download artifact + uses: actions/download-artifact@v4 + with: + name: winter-manifest + path: manifest + + - name: Commit changes + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: Update manifest + commit_user_name: Winter Bot + commit_user_email: 80384029+WinterCMSBot@users.noreply.github.com diff --git a/.github/workflows/subsplit.yml b/.github/workflows/subsplit.yml new file mode 100644 index 0000000..3347025 --- /dev/null +++ b/.github/workflows/subsplit.yml @@ -0,0 +1,32 @@ +name: Module sub-split + +on: + push: + # Branches only. Tag pushes are handled by the `create` event below; without + # this filter they would also fire here and pass the tag name to `split -b`, + # which then fails looking for a branch that doesn't exist. + branches: + - "**" + create: + delete: + +jobs: + split: + name: Sub-split + runs-on: ubuntu-latest + container: wintercms/cli:0.3.4 + env: + WINTER_CLI_GITHUB_TOKEN: ${{ secrets.WINTER_SPLIT_TOKEN }} + steps: + - name: Create tag + if: github.event_name == 'create' && github.ref_type == 'tag' + run: winter split -a "${{ github.ref_name }}" + - name: Delete branch + if: github.event_name == 'delete' && github.ref_type == 'branch' + run: winter split --remove-branch="${{ github.event.ref }}" + - name: Delete tag + if: github.event_name == 'delete' && github.ref_type == 'tag' + run: winter split --remove-tag="${{ github.event.ref }}" + - name: Push + if: github.event_name == 'push' + run: winter split -b "${{ github.ref_name }}" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..398fe5a --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,175 @@ +name: Tests + +on: + push: + branches: + - '1.2' + - develop + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + frontendTests: + strategy: + max-parallel: 2 + matrix: + operatingSystem: [ubuntu-latest, windows-latest] + fail-fast: false + runs-on: ${{ matrix.operatingSystem }} + name: ${{ matrix.operatingSystem }} / JavaScript + env: + nodeVersion: 16 + phpVersion: '8.2' + extensions: curl, fileinfo, gd, mbstring, openssl, pdo, pdo_sqlite, sqlite3, xml, zip + key: winter-cms-cache-develop + steps: + - name: Checkout changes + uses: actions/checkout@v3 + + - name: Setup extension cache + id: extcache + uses: shivammathur/cache-extensions@v1 + with: + php-version: ${{ env.phpVersion }} + extensions: ${{ env.extensions }} + key: ${{ env.key }} + + - name: Cache extensions + uses: actions/cache@v3 + with: + path: ${{ steps.extcache.outputs.dir }} + key: ${{ steps.extcache.outputs.key }} + restore-keys: ${{ steps.extcache.outputs.key }} + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ env.phpVersion }} + extensions: ${{ env.extensions }} + + - name: Install Node + uses: actions/setup-node@v3 + with: + node-version: ${{ env.nodeVersion }} + + - name: Switch library dependency (develop) + if: github.ref == 'refs/heads/develop' || github.base_ref == 'develop' + run: php ./.github/workflows/utilities/library-switcher "dev-develop as 1.2" + + - name: Switch library dependency (1.2) + if: github.head_ref == '1.2' || github.ref == 'refs/heads/1.2' || github.base_ref == '1.2' + run: php ./.github/workflows/utilities/library-switcher "1.2.x-dev as 1.2" + + - name: Setup dependency cache + id: composercache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composercache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-interaction --no-progress --no-scripts + + - name: Reset modules + run: | + git reset --hard + git clean -fd + + - name: Run post-update Composer scripts + run: php artisan package:discover + + - name: Run tests + run: | + php artisan mix:install + php artisan mix:run module-system test + + phpUnitTests: + strategy: + max-parallel: 8 + matrix: + operatingSystem: [ubuntu-latest, windows-latest] + phpVersion: ['8.1', '8.2', '8.3', '8.4', '8.5'] + fail-fast: false + runs-on: ${{ matrix.operatingSystem }} + name: ${{ matrix.operatingSystem }} / PHP ${{ matrix.phpVersion }} + env: + extensions: curl, fileinfo, gd, mbstring, openssl, pdo, pdo_sqlite, sqlite3, xml, zip + key: winter-cms-cache-develop + steps: + - name: Checkout changes + uses: actions/checkout@v3 + + - name: Setup extension cache + id: extcache + uses: shivammathur/cache-extensions@v1 + with: + php-version: ${{ matrix.phpVersion }} + extensions: ${{ env.extensions }} + key: ${{ env.key }} + + - name: Cache extensions + uses: actions/cache@v3 + with: + path: ${{ steps.extcache.outputs.dir }} + key: ${{ steps.extcache.outputs.key }} + restore-keys: ${{ steps.extcache.outputs.key }} + + - name: Install PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.phpVersion }} + extensions: ${{ env.extensions }} + + - name: Switch library dependency (develop) + if: github.ref == 'refs/heads/develop' || github.base_ref == 'develop' + run: php ./.github/workflows/utilities/library-switcher "dev-develop as 1.2" + + - name: Switch library dependency (1.0) + if: github.head_ref == '1.0' || github.ref == 'refs/heads/1.0' || github.base_ref == '1.0' + run: php ./.github/workflows/utilities/library-switcher "1.0.x-dev as 1.0" + + - name: Switch library dependency (1.1) + if: github.head_ref == '1.1' || github.ref == 'refs/heads/1.1' || github.base_ref == '1.1' + run: php ./.github/workflows/utilities/library-switcher "1.1.x-dev as 1.1" + + - name: Switch library dependency (1.2) + if: github.head_ref == '1.2' || github.ref == 'refs/heads/1.2' || github.base_ref == '1.2' + run: php ./.github/workflows/utilities/library-switcher "1.2.x-dev as 1.2" + + - name: Setup dependency cache + id: composercache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: ${{ steps.composercache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install Composer dependencies + run: composer install --no-interaction --no-progress --no-scripts + + - name: Reset modules + run: | + git reset --hard + git clean -fd + + - name: Run post-update Composer scripts + run: php artisan package:discover + + - name: Setup problem matchers for PHPUnit + if: matrix.phpVersion == '8.1' + run: echo "::add-matcher::${{ runner.tool_cache }}/phpunit.json" + + - name: Run Linting and Tests + run: | + composer lint + php artisan winter:test -m system -m backend -m cms diff --git a/.github/workflows/utilities/library-switcher b/.github/workflows/utilities/library-switcher new file mode 100755 index 0000000..e8839b9 --- /dev/null +++ b/.github/workflows/utilities/library-switcher @@ -0,0 +1,18 @@ +#!/usr/bin/env php + (($line[3] ?? 'err') === 'warning'), + 'message' => $line[4] ?? 'unknown', + 'line' => $line[1] ?? '0', + ]; +} + +// Render report +fwrite(STDERR, "\e[0;31mFound " + . ((count($lines) === 1) + ? '1 issue' + : count($lines) . ' issues') + . " with code quality.\e[0m"); +fwrite(STDERR, "\n"); + +foreach ($files as $file => $errors) { + fwrite(STDERR, "\n"); + fwrite(STDERR, "\e[1;37m" . str_replace('"', '', $file) . "\e[0m"); + fwrite(STDERR, "\n\n"); + + foreach ($errors as $error) { + fwrite(STDERR, "\e[2m" . str_pad(' L' . $error['line'], 7) . " | \e[0m"); + fwrite(STDERR, $error['warning'] ? "\e[1;33mWARN:\e[0m " : "\e[0;31mERR:\e[0m "); + fwrite(STDERR, $error['message']); + fwrite(STDERR, "\n"); + } +} + +exit(1); diff --git a/.github/workflows/utilities/phpcs-push b/.github/workflows/utilities/phpcs-push new file mode 100755 index 0000000..fe51c44 --- /dev/null +++ b/.github/workflows/utilities/phpcs-push @@ -0,0 +1,87 @@ +#!/usr/bin/env php + (($line[3] ?? 'err') === 'warning'), + 'message' => $line[4] ?? 'unknown', + 'line' => $line[1] ?? '0', + ]; +} + +// Render report +fwrite(STDERR, "\e[0;31mFound " + . ((count($lines) === 1) + ? '1 issue' + : count($lines) . ' issues') + . " with code quality.\e[0m"); +fwrite(STDERR, "\n"); + +foreach ($files as $file => $errors) { + fwrite(STDERR, "\n"); + fwrite(STDERR, "\e[1;37m" . str_replace('"', '', $file) . "\e[0m"); + fwrite(STDERR, "\n\n"); + + foreach ($errors as $error) { + fwrite(STDERR, "\e[2m" . str_pad(' L' . $error['line'], 7) . " | \e[0m"); + fwrite(STDERR, $error['warning'] ? "\e[1;33mWARN:\e[0m " : "\e[0;31mERR:\e[0m "); + fwrite(STDERR, $error['message']); + fwrite(STDERR, "\n"); + } +} +exit(1); + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a2907ef --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +/storage/ +/vendor/ +/node_modules/ +.env +composer.lock +*.sqlite +*.sqlite-journal diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..b6afe66 --- /dev/null +++ b/.htaccess @@ -0,0 +1,60 @@ + + + + Options -MultiViews + + + RewriteEngine On + + ## + ## You may need to uncomment the following line for some hosting environments, + ## if you have installed to a subdirectory, enter the name here also. + ## + # RewriteBase / + + ## + ## Uncomment following lines to force HTTPS. + ## + # RewriteCond %{HTTPS} off + # RewriteRule (.*) https://%{SERVER_NAME}/$1 [L,R=301] + + ## + ## Paths explicitly blocked from being handled by the server + ## + RewriteRule ^bootstrap/.* index.php [L,NC] + RewriteRule ^config/.* index.php [L,NC] + RewriteRule ^vendor/.* index.php [L,NC] + RewriteRule ^storage/cms/.* index.php [L,NC] + RewriteRule ^storage/logs/.* index.php [L,NC] + RewriteRule ^storage/framework/.* index.php [L,NC] + RewriteRule ^storage/temp/protected/.* index.php [L,NC] + RewriteRule ^storage/app/uploads/protected/.* index.php [L,NC] + + ## + ## Paths explicitly handled by the server + ## + RewriteCond %{REQUEST_FILENAME} -f + RewriteCond %{REQUEST_FILENAME} !/.well-known/* + RewriteCond %{REQUEST_FILENAME} !/storage/app/uploads/public/.* + RewriteCond %{REQUEST_FILENAME} !/storage/app/media/.* + RewriteCond %{REQUEST_FILENAME} !/storage/app/resized/.* + RewriteCond %{REQUEST_FILENAME} !/storage/temp/public/.* + RewriteCond %{REQUEST_FILENAME} !/themes/.*/(assets|resources)/.* + RewriteCond %{REQUEST_FILENAME} !/plugins/.*/(assets|resources)/.* + RewriteCond %{REQUEST_FILENAME} !/modules/.*/(assets|resources)/.* + RewriteRule !^index.php index.php [L,NC] + + ## + ## Block all PHP files, except index + ## + RewriteCond %{REQUEST_FILENAME} -f + RewriteCond %{REQUEST_FILENAME} \.php$ + RewriteRule !^index.php index.php [L,NC] + + ## + ## Standard routes + ## + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] + + diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..ab85385 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "wintercms.winter-cms" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..3211f57 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,41 @@ +{ + "files.associations": { + "**/modules/*/behaviors/*/partials/*.htm": "php", + "**/modules/*/blocks/*.block": "wintercms-block", + "**/modules/*/controllers/*/*.htm": "php", + "**/modules/*/formwidgets/*/partials/*.htm": "php", + "**/modules/*/layouts/*.htm": "php", + "**/modules/*/models/*/*.htm": "php", + "**/modules/*/partials/*.htm": "php", + "**/modules/*/reportwidgets/*/partials/*.htm": "php", + "**/modules/*/views/mail/*.htm": "wintercms", + "**/modules/*/widgets/*/partials/*.htm": "php", + + "**/plugins/*/*/behaviors/*/partials/*.htm": "php", + "**/plugins/*/*/blocks/*.block": "wintercms-block", + "**/plugins/*/*/components/**/*.htm": "wintercms-twig", + "**/plugins/*/*/controllers/*/*.htm": "php", + "**/plugins/*/*/formwidgets/*/partials/*.htm": "php", + "**/plugins/*/*/layouts/*.htm": "php", + "**/plugins/*/*/models/*/*.htm": "php", + "**/plugins/*/*/partials/*.htm": "php", + "**/plugins/*/*/reportwidgets/*/partials/*.htm": "php", + "**/plugins/*/*/views/mail/*.htm": "wintercms", + "**/plugins/*/*/widgets/*/partials/*.htm": "php", + + "**/themes/*/blocks/**/*.block": "wintercms-block", + "**/themes/*/content/**/*.htm": "wintercms", + "**/themes/*/layouts/*.htm": "wintercms", + "**/themes/*/pages/**/*.htm": "wintercms", + "**/themes/*/partials/**/*.htm": "wintercms" + }, + "emmet.includeLanguages": { + "wintercms": "html", + "wintercms-twig": "html", + "wintercms-block": "html" + }, + "eslint.validate": [ + "javascript", + "vue" + ] +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..2fe8e8d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,95 @@ +# Agent guide — Winter CMS core + +Winter core sits on top of [Winter Storm](https://github.com/wintercms/storm) (installed at `vendor/winter/storm/`), which sits on top of Laravel, which sits on top of Symfony components. The helper you want almost certainly already exists at one of those layers. **Search Storm → Laravel → Symfony before writing any "small utility"**, often with safer edge-case handling than a fresh implementation would have. + +## Where to look (in this order) + +1. **Storm itself** — each `vendor/winter/storm/src//README.md` catalogues that module's public API: + - `Filesystem/` — `PathResolver` (`resolve`, `within`, `join`, `standardize`), `Filesystem` (extends Illuminate's; adds `isAbsolutePath`, `symbolizePath`, `existsInsensitive`, `chmodRecursive`) + - `Support/` — strings, arrays, class loading + - `Network/`, `Html/`, `Parse/`, `Database/`, `Halcyon/`, `Auth/`, etc. + - Path helpers (always loaded): `themes_path()`, `plugins_path()`, `media_path()`, `uploads_path()`, `temp_path()` — use these instead of `base_path('themes')` etc. + +2. **Laravel (Illuminate)** — everything Laravel ships is available: + - `Illuminate\Support\Str` — `Str::startsWith/endsWith/contains/before/after/between/slug/camel/snake/kebab/studly/random/uuid/limit/mask/finish/start/of/headline/title`. Use instead of regex one-liners. + - `Illuminate\Support\Arr` — `Arr::get/set/has/forget/only/except/dot/undot/flatten/pluck/wrap/first/last/where`. Use instead of nested foreach. + - `Illuminate\Support\Collection` (via `collect()`) — chainable map/filter/reduce. + - `Illuminate\Filesystem\Filesystem` — `deleteDirectory()`, `cleanDirectory()`, `copyDirectory()`, `moveDirectory()`, `allFiles()`, `glob()`, `isDirectory()`, `prepend()`, `append()`, `replace()`, `hash()`. + - Global helpers: `data_get/set/fill`, `value`, `tap`, `optional`, `transform`, `head`, `last`, `class_basename`, `now`, `today`, `e`, `__`/`trans`, `cache`, `config`, `env`, `app`, `resolve`, `route`, `url`, `report`, `rescue`, `retry`, `throw_if`/`unless`, `abort`/`abort_if`/`unless`. + - Facades: `Cache`, `Config`, `DB`, `Event`, `File`, `Hash`, `Http`, `Lang`, `Log`, `Mail`, `Queue`, `Redis`, `Route`, `Schema`, `Session`, `Storage`, `URL`, `Validator`, `View`. + +3. **Symfony components** at `vendor/symfony/`: `console`, `css-selector`, `error-handler`, `event-dispatcher`, `finder`, `http-foundation`, `http-kernel`, `mailer`, `mime`, `process`, `routing`, `string`, `translation`, `uid`, `var-dumper`, `yaml`. Most commonly reached for: + - `Symfony\Component\Finder\Finder` — `Finder::create()->files()->name('*.less')->in($dir)` replaces RecursiveIteratorIterator chains. + - `Symfony\Component\Filesystem\Filesystem` — `dumpFile()` (atomic write), `mirror()`, `mkdir()` (idempotent), `remove()`, `symlink()`. + - `Symfony\Component\Process\Process` — safe external command execution instead of `exec()`/`shell_exec()`. + - `Symfony\Component\Yaml\Yaml` — strict YAML. + - `Symfony\Component\String\` — Unicode-aware strings. + - `Symfony\Component\Uid\Uuid`/`Ulid` — UUID/ULID generation. + +`grep -rl 'function ' vendor/winter/storm/src/ vendor/laravel/framework/src/ vendor/symfony/` is a 10-second check. + +## Concrete substitutions worth memorising + +Paths and filesystem: + +| If you reach for… | Use this instead | +|---|---| +| `realpath()` + null-check + slash-trim | `\Winter\Storm\Filesystem\PathResolver::resolve()` | +| `str_starts_with($path, $root)` to gate file access | `PathResolver::within($path, $root)` — separator-boundary safe | +| Manual `base_path('themes')` / `base_path('plugins')` | `themes_path()` / `plugins_path()` (Storm's autoloaded helpers) | +| Recursive `rmrf` in tests | `\File::deleteDirectory($path)` (Laravel facade) | +| Detect absolute path | `(new \Winter\Storm\Filesystem\Filesystem())->isAbsolutePath($path)` | +| Custom path-symbol resolution (`~/...`) | `(new \Winter\Storm\Filesystem\Filesystem())->symbolizePath($path)` | +| `str_replace('\\', '/', $path)` (cross-platform comparison) | `(new \Winter\Storm\Filesystem\Filesystem())->normalizePath($path)` | +| `str_replace('/', DIRECTORY_SEPARATOR, $path)` (handing to OS API) | `\Winter\Storm\Filesystem\PathResolver::standardize($path)` | +| Atomic file write (avoid partial-write races) | `(new \Symfony\Component\Filesystem\Filesystem())->dumpFile($path, $contents)` | +| Find files matching a pattern | `\Symfony\Component\Finder\Finder::create()->files()->name('*.ext')->in($dir)` | + +Strings and arrays: + +| If you reach for… | Use this instead | +|---|---| +| `preg_match('/^prefix/', $s)` | `Str::startsWith($s, 'prefix')` (accepts array of prefixes) | +| Manual `strpos !== false` | `Str::contains($s, $needle)` | +| `strtolower`-then-replace slug generation | `Str::slug($s)` | +| Random hex/string for tmp paths, tokens | `Str::random()` / `Str::uuid()` | +| Deep array key access with null safety | `data_get($array, 'a.b.c', $default)` | +| Pulling subset of array keys | `Arr::only($array, [...])` / `Arr::except($array, [...])` | +| Chained map / filter / reduce on array | `collect($array)->filter(...)->map(...)->values()->all()` | + +Other: + +| If you reach for… | Use this instead | +|---|---| +| `exec()` / `shell_exec()` / backticks | `(new \Symfony\Component\Process\Process([$cmd, ...$args]))->mustRun()` | +| Manual YAML parsing | `\Symfony\Component\Yaml\Yaml::parse()` | +| JSON parsing without strict error handling | `json_decode($s, true, 512, JSON_THROW_ON_ERROR)` | +| UUID generation by `random_bytes` + hex shuffle | `Str::uuid()` or `\Symfony\Component\Uid\Uuid::v7()` | +| HTTP request to external service | Laravel's `\Http::get(...)` facade | + +## Layering boundaries + +Storm depends on Laravel + Symfony pieces. It must **not** depend on Winter modules. Conversely, Winter core modules are free to use Storm. So: + +- CMS / theme / plugin / system concerns live in `modules/` (backend, cms, system). +- Generic filesystem, path, parser, network primitives live in `vendor/winter/storm/`. +- When a Storm class needs a *policy* that's CMS-specific (e.g. "which directories count as theme asset roots"), expose a public setter on the Storm class and have the module-level caller supply the policy. Don't reach into module-level constants from Storm. + +## Autoloading & file placement + +Modules and plugins are autoloaded by `Winter\Storm\Support\ClassLoader` (see `ClassLoader::load()`), **not** plain PSR-4. Its convention: the namespace's **directory segments are lower-cased** to form the path, while the class file keeps its proper PascalCase name. So `System\Twig\SecurityPolicy\SafeCollection` resolves to `modules/system/twig/securitypolicy/SafeCollection.php` — note the lowercase `securitypolicy/` directory. + +- **New sub-namespace directories must be lowercase on disk**, even though the namespace segment stays PascalCase: `System\Twig\Node` → `modules/system/twig/node/`, not `Node/`. The file name keeps its PascalCase and must match the class name exactly. +- This only bites on case-sensitive filesystems: a capitalized directory works on macOS/Windows (case-insensitive) and passes local tests, then fails Linux CI with `Class "…" not found`. **If Windows CI is green but every Ubuntu job fails to find a class, suspect a directory-case mismatch.** + +## Tests + +- Backend/CMS/system tests usually extend `System\Tests\Bootstrap\PluginTestCase` (boots Laravel, plugins, auth) or `System\Tests\Bootstrap\TestCase` (boots the framework but not plugins). +- Fixtures that flow through `Assetic\Asset\FileAsset` (e.g. `CombineAssets::combineToFile()`) must live under `base_path()`. `sys_get_temp_dir()` will fail with "source is not in the root directory". Use `base_path('storage/framework/cache/')` for temp dirs and clean up with `\File::deleteDirectory()` in `tearDown()`. +- A failing test that doesn't reproduce on a fresh clone is almost always a stale local `vendor/`. Run `composer update` in Storm (`~/Repositories/WinterCMS/Core/storm` or wherever you check it out) before claiming "environment issue". + +## Working across Winter core + Storm + +When a change touches both, work in the actual local checkouts (e.g. `~/Repositories/WinterCMS/Core/storm` and `~/Repositories/WinterCMS/Core/winter`) on parallel branches, and symlink `vendor/winter/storm` to the local Storm checkout so changes are visible in the live install. Avoid `/tmp` worktrees — the user can't test what they can't see. + +Open both PRs concurrently; the maintainer handles merge order and Storm release tagging. The Winter core PR's `composer.json` constraint bump waits for the Storm tag. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..6331924 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1 @@ +View the changelog on the [meta repository](https://github.com/wintercms/meta/tree/master/release-notes) diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b868eeb --- /dev/null +++ b/Dockerfile @@ -0,0 +1,45 @@ +FROM php:8.2-apache-bookworm + +LABEL coolify.managed=true +LABEL maintainer="VivesPOS" + +ENV APACHE_DOCUMENT_ROOT=/var/www/html +ENV COMPOSER_ALLOW_SUPERUSER=1 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + libpng-dev libjpeg-dev libfreetype6-dev libzip-dev libsqlite3-dev \ + unzip git curl && \ + docker-php-ext-configure gd --with-freetype --with-jpeg && \ + docker-php-ext-install gd zip pdo_sqlite pdo_mysql mbstring exif opcache && \ + a2enmod rewrite headers expires && \ + curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \ + apt-get clean && rm -rf /var/lib/apt/lists/* + +RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' \ + /etc/apache2/sites-available/*.conf && \ + sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' \ + /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf && \ + printf '\n AllowOverride All\n Require all granted\n\n' \ + > /etc/apache2/conf-available/vivespos.conf && \ + a2enconf vivespos + +WORKDIR /var/www/html + +COPY . . + +RUN composer install --no-dev --optimize-autoloader --no-interaction || true + +RUN php artisan winter:version 2>/dev/null || true + +RUN php artisan key:generate --force 2>/dev/null || true + +RUN chown -R www-data:www-data /var/www/html && \ + chmod -R 755 /var/www/html && \ + chmod -R 777 storage bootstrap/cache themes plugins + +EXPOSE 80 + +HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ + CMD curl -f http://localhost:80/ || exit 1 + +CMD ["apache2-foreground"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7b47a3b --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2013-2021.03.01 October CMS +Copyright (c) 2021 Winter CMS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..537b95d --- /dev/null +++ b/README.md @@ -0,0 +1,115 @@ +

+ Winter CMS Logo +

+ +[Winter](https://wintercms.com) is a free, open-source content management system based on the [Laravel](https://laravel.com) PHP framework. Developers and agencies all around the world rely upon Winter for its quick prototyping and development, safe and secure codebase and dedication to simplicity. + +No matter how large or small your project is, Winter provides a rich development environment, regardless of your level of experience. + +[![Version](https://img.shields.io/github/v/release/wintercms/winter?sort=semver&style=flat-square)](https://github.com/wintercms/winter/releases) +[![Tests](https://img.shields.io/github/actions/workflow/status/wintercms/winter/tests.yml?branch=develop&label=tests&style=flat-square)](https://github.com/wintercms/winter/actions) +[![License](https://img.shields.io/github/license/wintercms/winter?label=open%20source&style=flat-square)](https://packagist.org/packages/wintercms/winter) +[![Discord](https://img.shields.io/badge/discord-join-purple?style=flat-square&logo=discord&logoColor=white)](https://discord.gg/D5MFSPH6Ux) + +## Installing Winter + +Winter can be installed in several ways for both new users and experienced developers - see our [Installation page](https://wintercms.com/install) for more information. + +### Quick start with Composer + +For advanced users, run the following command in your terminal to install Winter via Composer: + +```shell +composer create-project wintercms/winter example.com "dev-develop" +``` + +Run the following command with the folder created by the previous command to generate an environment file which will contain your configuration settings: + +```shell +php artisan winter:env +``` + +After configuring your installation, you can run the following command to run the database migrations and automatically create an administrator account with the username `admin`. The password of this account will be automatically generated and displayed in your terminal. + +```shell +php artisan winter:up +``` + +## Learning Winter + +The best place to learn Winter is by [reading the documentation](https://wintercms.com/docs) or [following some tutorials](https://wintercms.com/blog/category/tutorials). You can also join the maintenance team and our active community on [Discord](https://discord.gg/D5MFSPH6Ux) who are always willing to help out with questions. + +## Development team + +Winter was forked from October CMS in March 2021 due to a difference in open source management philosophies between the core maintainer team and the two founders of October. + +The development of Winter is lead by [Luke Towers](https://luketowers.ca/), along with many wonderful people that dedicate their time to help support and grow the community. The [Frostbyte Foundation](mailto:hello@frostbytefoundation.org) provides an organisational backing for the project and the continued development of Winter, its plugins and themes and its ecosystem. + + + + + + + + + +
Luke Towers
Luke Towers
Ben Thomson
Ben Thomson
Marc Jauvin
Marc Jauvin
Jack Wilkinson
Jack Wilkinson
Damien Mathieu
Damien Mathieu
+ +## Foundation library + +Winter is built on top of the wildly-popular [Laravel](https://laravel.com) framework for PHP, with the in-house [Storm](https://github.com/wintercms/storm) library as a buffer between the Laravel framework and the Winter project, to minimize breaking changes and improve stability. + +## Getting in touch + +You can get in touch with the maintainer team using the following mediums: + +* [Follow us on Twitter](https://twitter.com/usewintercms) for announcements and updates. +* [Join us on Discord](https://discord.gg/D5MFSPH6Ux) to chat with us. + +## Contributing + +Before contributing issues or pull requests, be sure to review the [Contributing Guidelines](https://github.com/wintercms/.github/blob/master/CONTRIBUTING.md) first. + +### Coding standards + +Please follow the following guides and code standards: + +* [PSR 4 Coding Standards](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-4-autoloader.md) +* [PSR 2 Coding Style Guide](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) +* [PSR 1 Coding Standards](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-1-basic-coding-standard.md) + +### Code of conduct + +In order to ensure that the Winter community is welcoming to all, please review and abide by the [Code of Conduct](https://github.com/wintercms/.github/blob/master/CODE_OF_CONDUCT.md). + +## Sponsors + +Winter CMS development is financially supported by the generosity of the following sponsors. If you would like to have your name, company and link added to this list and support open-source development, feel free to make a donation to our [Open Collective](https://opencollective.com/wintercms). + +### Organizations + + + Laravel logo + + +Laravel provides [Laravel Vapor](https://vapor.laravel.com/?ref=wintercms) to the Winter CMS project which is used to power the serverless PHP hosting used for our [main website and documentation](https://wintercms.com/). + + + Froala logo + + +Froala provides a perpetual, Enterprise license to Winter CMS which allows us and our users to use the Froala WYSIWYG Editor in Winter CMS powered projects. + +### Individuals + +Big thanks to our sponsors on OpenCollective: + +- Orville + +## License + +The Winter platform is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). + +## Security vulnerabilities + +Please review [our security policy](https://github.com/wintercms/winter/security/policy) on how to report security vulnerabilities. diff --git a/artisan b/artisan new file mode 100755 index 0000000..8d1e73f --- /dev/null +++ b/artisan @@ -0,0 +1,51 @@ +#!/usr/bin/env php +make(Illuminate\Contracts\Console\Kernel::class); + +$status = $kernel->handle( + $input = new Symfony\Component\Console\Input\ArgvInput, + new Symfony\Component\Console\Output\ConsoleOutput +); + +/* +|-------------------------------------------------------------------------- +| Shutdown The Application +|-------------------------------------------------------------------------- +| +| Once Artisan has finished running, we will fire off the shutdown events +| so that any final work may be done by the application before we shut +| down the process. This is the last thing to happen to the request. +| +*/ + +$kernel->terminate($input, $status); + +exit($status); diff --git a/bootstrap/app.php b/bootstrap/app.php new file mode 100644 index 0000000..10e92d3 --- /dev/null +++ b/bootstrap/app.php @@ -0,0 +1,55 @@ +singleton( + Illuminate\Contracts\Http\Kernel::class, + Winter\Storm\Foundation\Http\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Console\Kernel::class, + Winter\Storm\Foundation\Console\Kernel::class +); + +$app->singleton( + Illuminate\Contracts\Debug\ExceptionHandler::class, + Winter\Storm\Foundation\Exception\Handler::class +); + +/* +|-------------------------------------------------------------------------- +| Return The Application +|-------------------------------------------------------------------------- +| +| This script returns the application instance. The instance is given to +| the calling script so we can separate the building of the instances +| from the actual running of the application and sending responses. +| +*/ + +return $app; diff --git a/bootstrap/autoload.php b/bootstrap/autoload.php new file mode 100644 index 0000000..429da18 --- /dev/null +++ b/bootstrap/autoload.php @@ -0,0 +1,38 @@ +=8.1", + "winter/storm": "~1.2.0", + "winter/wn-system-module": "~1.2.0", + "winter/wn-backend-module": "~1.2.0", + "winter/wn-cms-module": "~1.2.0", + "laravel/framework": "^9.1", + "wikimedia/composer-merge-plugin": "~2.1.0", + "winter/wn-pages-plugin": "~1.2.0", + "winter/wn-blog-plugin": "~1.2.0", + "winter/wn-sitemap-plugin": "~1.2.0", + "winter/wn-seo-plugin": "~1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5.8", + "mockery/mockery": "^1.4.4", + "fakerphp/faker": "^1.9.2", + "squizlabs/php_codesniffer": "^3.2", + "php-parallel-lint/php-parallel-lint": "^1.0", + "dms/phpunit-arraysubset-asserts": "^0.1.0|^0.2.1" + }, + "scripts": { + "post-create-project-cmd": [ + "@php artisan winter:install", + "@php artisan winter:env", + "@php artisan winter:mirror public --relative" + ], + "post-update-cmd": [ + "@php artisan winter:version", + "@php artisan package:discover" + ], + "test": [ + "phpunit --stop-on-failure" + ], + "lint": [ + "parallel-lint --exclude vendor --exclude storage --exclude modules/system/tests/fixtures/plugins/testvendor/goto/Plugin.php ." + ], + "sniff": [ + "phpcs --colors -nq --report=\"full\" --extensions=\"php\"" + ] + }, + "minimum-stability": "dev", + "prefer-stable": true, + "extra": { + "merge-plugin": { + "include": [ + "plugins/myauthor/*/composer.json", + "plugins/vivespos/*/composer.json" + ], + "recurse": true, + "replace": false, + "merge-replace": false, + "merge-dev": false + } + }, + "config": { + "allow-plugins": { + "composer/installers": true, + "wikimedia/composer-merge-plugin": true + } + } +} diff --git a/config/app.php b/config/app.php new file mode 100644 index 0000000..e4a78cb --- /dev/null +++ b/config/app.php @@ -0,0 +1,322 @@ + env('APP_DEBUG', true), + + /* + |-------------------------------------------------------------------------- + | Application Name + |-------------------------------------------------------------------------- + | + | This value is the name of your application. This value is used when the + | framework needs to place the application's name in a notification or + | any other location as required by the application or its packages. + | + */ + + 'name' => env('APP_NAME', 'Winter CMS'), + + /* + |-------------------------------------------------------------------------- + | Application URL + |-------------------------------------------------------------------------- + | + | This URL is used by the console to properly generate URLs when using + | the Artisan command line tool. You should set this to the root of + | your application so that it is used when running Artisan tasks. + | + */ + + 'url' => env('APP_URL', 'http://localhost'), + + /* + |-------------------------------------------------------------------------- + | Asset URL + |-------------------------------------------------------------------------- + | + | This URL is used to properly generate URLs for assets, including + | URLs generated by the `| theme` & `| asset` filters in Twig, or the + | `Url::asset()` & `asset()` helpers. If set to null, the URL used will + | be the current hostname or `app.url` config. + | + | 'asset_url' => 'https://cdn.example.com/', + | + */ + + 'asset_url' => env('ASSET_URL', null), + + /* + |-------------------------------------------------------------------------- + | Temporary Path + |-------------------------------------------------------------------------- + | + | This is used to set the application's temporary path. Normally this value + | is set automatically by the application, however on some systems you + | may need to change it (Laravel Vapor / read-only systems: /tmp). + | + */ + + 'tempPath' => env('APP_TEMP_PATH', null), + + /* + |-------------------------------------------------------------------------- + | Trusted hosts + |-------------------------------------------------------------------------- + | + | You may specify valid hosts for your application as an array or boolean + | below. This helps prevent host header poisoning attacks. + | + | Possible values: + | - `true`: Trust the host specified in app.url, as well as the "www" + | subdomain, if applicable. + | - `false`: Disable the trusted hosts feature. + | - array: Defines the domains to be trusted hosts. Each item should be + | a string defining a domain, IP address, or a regex pattern. + | + | Example of array values: + | + | 'trustedHosts' => [ + | 'example.com', // Matches just example.com + | 'www.example.com', // Matches just www.example.com + | '^(.+\.)?example\.com$', // Matches example.com and all subdomains + | 'https://example.com', // Matches just example.com + | ], + | + | NOTE: Even when set to `false`, this functionality is explicitly enabled + | on the Backend password reset flow for security reasons. + */ + + 'trustedHosts' => false, + + /* + |-------------------------------------------------------------------------- + | Trusted proxies + |-------------------------------------------------------------------------- + | + | You may specify valid proxies for your application, in order for URLs + | and requests to be presented as the proxy address should you request + | a URL through the proxy. + | + | Possible values: + | - `null` or `false`: Do not trust any proxies + | - `'*'`: Trust all proxies + | - string: A single or comma-separated list of proxies to trust + | - array: An array of proxies to trust + | + | Examples: + | - To trust any proxy (i.e. a single proxy with an unknown IP address): + | + | 'trustedProxies' => '*', + | + | - To trust all proxies (i.e. AWS ELB behind CloudFront): + | + | 'trustedProxies' => '**', + | + | - To trust two IP addresses as proxies + | + | 'trustedProxies' => '192.168.1.1, 192.168.1.2', + | 'trustedProxies' => ['192.168.1.1', '192.168.1.2'], + */ + + 'trustedProxies' => null, + + /* + |-------------------------------------------------------------------------- + | Trusted proxy headers + |-------------------------------------------------------------------------- + | + | In addition to the above, you can also determine which headers to trust + | from your proxy when rewriting the request. This is an integer map value + | so you may specify more than one value. + | + | Possible values: + | - 'HEADER_X_FORWARDED_ALL' - trust all forwarded headers + | - Illuminate\Http\Request::HEADER_X_FORWARDED_FOR - trust only the proxy IP + | - Illuminate\Http\Request::HEADER_X_FORWARDED_HOST - trust only the proxy hostname + | - Illuminate\Http\Request::HEADER_X_FORWARDED_PORT - trust only the proxy port + | - Illuminate\Http\Request::HEADER_X_FORWARDED_PROTO - trust only the proxy protocol + | - Illuminate\Http\Request::HEADER_X_FORWARDED_PREFIX - trust only the proxy prefix + | - Illuminate\Http\Request::HEADER_X_FORWARDED_AWS_ELB - trust Amazon Elastic Load Balancing headers + | - Illuminate\Http\Request::HEADER_X_FORWARDED_TRAEFIK - trust Traefik reverse proxy headers + | + | Examples: + | - To trust only the hostname, use the following: + | + | 'trustedProxyHeaders' => Illuminate\Http\Request::HEADER_X_FORWARDED_HOST + | + | - For trusting all except the protocol, you can use the following: + | + | 'trustedProxyHeaders' => Illuminate\Http\Request::HEADER_X_FORWARDED_FOR + | | Illuminate\Http\Request::HEADER_X_FORWARDED_HOST + | | Illuminate\Http\Request::HEADER_X_FORWARDED_PORT + | + | - Amazon ELB users should always use the "HEADER_X_FORWARDED_AWS_ELB" option. + */ + + 'trustedProxyHeaders' => 'HEADER_X_FORWARDED_ALL', + + /* + |-------------------------------------------------------------------------- + | Application Timezone + |-------------------------------------------------------------------------- + | + | Here you may specify the default timezone for your application, which + | will be used by the PHP date and date-time functions. We have gone + | ahead and set this to a sensible default for you out of the box. + | + | + | -------- STOP! -------- + | Before you change this value, consider carefully if that is actually + | what you want to do. It is HIGHLY recommended that this is always set + | to UTC (as your server & DB timezone should be as well) and instead you + | use cms.backendTimezone to set the default timezone used in the backend + | to display dates & times. + | + */ + + 'timezone' => 'UTC', + + /* + |-------------------------------------------------------------------------- + | Scheduler Timezone + |-------------------------------------------------------------------------- + | + | This property specifies the default timezone for your application's + | scheduled tasks. You can set it independently of the application's + | default timezone to ensure that schedules run at the desired local time. + | + */ + + 'schedule_timezone' => 'UTC', + + /* + |-------------------------------------------------------------------------- + | Application Locale Configuration + |-------------------------------------------------------------------------- + | + | The application locale determines the default locale that will be used + | by the translation service provider. You are free to set this value + | to any of the locales which will be supported by the application. + | + | WARNING: Avoid setting this to a locale that is not supported by the + | backend yet, as this can cause issues in the backend. + | + | Currently supported backend locales are listed in + | Backend\Models\Preference->getLocaleOptions() + | + */ + + 'locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Application Fallback Locale + |-------------------------------------------------------------------------- + | + | The fallback locale determines the locale to use when the current one + | is not available. You may change the value to correspond to any of + | the language folders that are provided through your application. + | + */ + + 'fallback_locale' => 'en', + + /* + |-------------------------------------------------------------------------- + | Faker Locale + |-------------------------------------------------------------------------- + | + | This locale will be used by the Faker PHP library when generating fake + | data for your database seeds. For example, this will be used to get + | localized telephone numbers, street address information and more. + | + */ + + 'faker_locale' => 'en_US', + + /* + |-------------------------------------------------------------------------- + | Encryption Key + |-------------------------------------------------------------------------- + | + | This key is used by the Illuminate encrypter service and should be set + | to a random, 32 character string, otherwise these encrypted strings + | will not be safe. Please do this before deploying an application! + | + */ + + 'key' => env('APP_KEY'), + 'cipher' => 'AES-256-CBC', + + /* + |-------------------------------------------------------------------------- + | Autoloaded Service Providers + |-------------------------------------------------------------------------- + | + | The service providers listed here will be automatically loaded on the + | request to your application. Feel free to add your own services to + | this array to grant expanded functionality to your applications. + | + */ + + 'providers' => array_merge(include(base_path('modules/system/providers.php')), [ + + // 'Illuminate\Html\HtmlServiceProvider', // Example + + System\ServiceProvider::class, + ]), + + /* + |-------------------------------------------------------------------------- + | Load automatically discovered packages + |-------------------------------------------------------------------------- + | + | By default, Winter CMS disables the loading of discovered packages + | through Laravel's package discovery service, in order to allow packages + | used by plugins to be disabled if the plugin itself is disabled. + | + | Set this to `true` to enable automatic loading of these packages. This + | will result in packages being loaded, even if the plugin using them is + | disabled. This is NOT RECOMMENDED. + | + | Please note that packages defined in `app.providers` will still be loaded + | even if discovery is disabled. + | + */ + + 'loadDiscoveredPackages' => false, + + /* + |-------------------------------------------------------------------------- + | Class Aliases + |-------------------------------------------------------------------------- + | + | This array of class aliases will be registered when this application + | is started. However, feel free to register as many as you wish as + | the aliases are "lazy" loaded so they don't hinder performance. + | + */ + + 'aliases' => array_merge(include(base_path('modules/system/aliases.php')), [ + // 'Str' => 'Illuminate\Support\Str', // Example + ]), +]; diff --git a/config/auth.php b/config/auth.php new file mode 100644 index 0000000..846e31a --- /dev/null +++ b/config/auth.php @@ -0,0 +1,41 @@ + [ + + /* + |-------------------------------------------------------------------------- + | Enable throttling of Backend authentication attempts + |-------------------------------------------------------------------------- + | + | If set to true, users will be given a limited number of attempts to sign + | in to the Backend before being blocked for a specified number of minutes. + | + */ + + 'enabled' => true, + + /* + |-------------------------------------------------------------------------- + | Failed Authentication Attempt Limit + |-------------------------------------------------------------------------- + | + | Number of failed attempts allowed while trying to authenticate a user. + | + */ + + 'attemptLimit' => 5, + + /* + |-------------------------------------------------------------------------- + | Suspension Time + |-------------------------------------------------------------------------- + | + | The number of minutes to suspend further attempts on authentication once + | the attempt limit is reached. + | + */ + + 'suspensionTime' => 15, + ], +]; diff --git a/config/broadcasting.php b/config/broadcasting.php new file mode 100644 index 0000000..948f010 --- /dev/null +++ b/config/broadcasting.php @@ -0,0 +1,60 @@ + env('BROADCAST_DRIVER', 'null'), + + /* + |-------------------------------------------------------------------------- + | Broadcast Connections + |-------------------------------------------------------------------------- + | + | Here you may define all of the broadcast connections that will be used + | to broadcast events to other systems or over websockets. Samples of + | each available type of connection are provided inside this array. + | + */ + + 'connections' => [ + 'pusher' => [ + 'app_id' => env('PUSHER_APP_ID'), + 'client_options' => [ + // Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html + ], + 'driver' => 'pusher', + 'key' => env('PUSHER_APP_KEY'), + 'options' => [ + 'cluster' => env('PUSHER_APP_CLUSTER'), + 'useTLS' => true, + ], + 'secret' => env('PUSHER_APP_SECRET'), + ], + 'ably' => [ + 'driver' => 'ably', + 'key' => env('ABLY_KEY'), + ], + 'redis' => [ + 'connection' => 'default', + 'driver' => 'redis', + ], + 'log' => [ + 'driver' => 'log', + ], + 'null' => [ + 'driver' => 'null', + ], + ], +]; diff --git a/config/cache.php b/config/cache.php new file mode 100644 index 0000000..c689a4b --- /dev/null +++ b/config/cache.php @@ -0,0 +1,139 @@ + env('CACHE_DRIVER', 'file'), + + /* + |-------------------------------------------------------------------------- + | Cache Stores + |-------------------------------------------------------------------------- + | + | Here you may define all of the cache "stores" for your application as + | well as their drivers. You may even define multiple stores for the + | same cache driver to group types of items stored in your caches. + | + | Supported drivers: "apc", "array", "database", "file", + | "memcached", "redis", "dynamodb", "octane", "null" + | + */ + + 'stores' => [ + 'apc' => [ + 'driver' => 'apc', + ], + 'array' => [ + 'driver' => 'array', + 'serialize' => false, + ], + 'database' => [ + 'connection' => null, + 'driver' => 'database', + 'lock_connection' => null, + 'table' => 'cache', + ], + 'file' => [ + 'driver' => 'file', + 'path' => storage_path('framework/cache'), + ], + 'memcached' => [ + 'driver' => 'memcached', + 'options' => [ + // Memcached::OPT_CONNECT_TIMEOUT => 2000, + ], + 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), + 'sasl' => [ + env('MEMCACHED_USERNAME'), + env('MEMCACHED_PASSWORD'), + ], + 'servers' => [ + [ + 'host' => env('MEMCACHED_HOST', '127.0.0.1'), + 'port' => env('MEMCACHED_PORT', 11211), + 'weight' => 100, + ], + ], + ], + 'redis' => [ + 'connection' => 'cache', + 'driver' => 'redis', + 'lock_connection' => 'default', + ], + 'dynamodb' => [ + 'driver' => 'dynamodb', + 'endpoint' => env('DYNAMODB_ENDPOINT'), + 'key' => env('AWS_ACCESS_KEY_ID'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), + ], + 'octane' => [ + 'driver' => 'octane', + ], + ], + + /* + |-------------------------------------------------------------------------- + | Cache Key Prefix + |-------------------------------------------------------------------------- + | + | When utilizing a RAM based store such as APC or Memcached, there might + | be other applications utilizing the same cache. So, we'll specify a + | value to get prefixed to all our keys so we can avoid collisions. + | + */ + + 'prefix' => env('CACHE_PREFIX', str_slug(env('APP_NAME', 'winter'), '_') . '_cache'), + + /* + |-------------------------------------------------------------------------- + | Cache Key for the CMS' PHP code parser cache + |-------------------------------------------------------------------------- + | + | This option controls the cache key used by the CMS when storing generated + | PHP from the theme PHP sections. Recommended to change this when multiple + | servers running Winter CMS are connected to the same cache server to + | prevent conflicts. + | + */ + + 'codeParserDataCacheKey' => 'cms-php-file-data', + + /* + |-------------------------------------------------------------------------- + | Disable Request Cache + |-------------------------------------------------------------------------- + | + | The request cache stores cache retrievals from the cache store + | in memory to speed up consecutive retrievals within the same request. + | + | true - always disable this in-memory request cache + | + | false - always enable; be aware that long-running console commands + | (including queue workers) may retain cache entries in memory that + | have been changed in other processes or would have otherwise + | expired, causing issues with the `queue:restart` command, for + | example + | + | null - enable for HTTP requests, disable when running in CLI + | + */ + + 'disableRequestCache' => null, +]; diff --git a/config/cms.php b/config/cms.php new file mode 100644 index 0000000..f604eb9 --- /dev/null +++ b/config/cms.php @@ -0,0 +1,476 @@ + 'vivespos', + + /* + |-------------------------------------------------------------------------- + | Bleeding edge updates + |-------------------------------------------------------------------------- + | + | If you are developing with Winter, it is important to have the latest + | code base. Set this value to 'true' to tell the platform to download + | and use the development copies of core files and plugins. + | + */ + + 'edgeUpdates' => false, + + /* + |-------------------------------------------------------------------------- + | Back-end URI prefix + |-------------------------------------------------------------------------- + | + | Specifies the URL name used for accessing back-end pages. + | For example: backend -> http://localhost/backend + | + */ + + 'backendUri' => 'backend', + + /* + |-------------------------------------------------------------------------- + | Back-end force HTTPS security + |-------------------------------------------------------------------------- + | + | Use this setting to force a secure protocol when accessing any back-end + | pages, including the authentication pages. This is usually handled by + | web server config, but can be handled by the app for added security. + | + */ + + 'backendForceSecure' => false, + + /* + |-------------------------------------------------------------------------- + | Back-end login remember + |-------------------------------------------------------------------------- + | + | Define live duration of backend sessions: + | + | true - session never expire (cookie expiration in 5 years) + | + | false - session have a limited time (see session.lifetime) + | + | null - The form login display a checkbox that allow user to choose + | wanted behavior + | + */ + + 'backendForceRemember' => true, + + /* + |-------------------------------------------------------------------------- + | Back-end timezone + |-------------------------------------------------------------------------- + | + | This acts as the default setting for a back-end user's timezone. This can + | be changed by the user at any time using the backend preferences. All + | dates displayed in the back-end will be converted to this timezone. + | + */ + + 'backendTimezone' => 'UTC', + + /* + |-------------------------------------------------------------------------- + | Back-end Skin + |-------------------------------------------------------------------------- + | + | Specifies the back-end skin to use. + | + */ + + 'backendSkin' => \Backend\Skins\Standard::class, + + /* + |-------------------------------------------------------------------------- + | Automatically run migrations on login + |-------------------------------------------------------------------------- + | + | If value is true, UpdateManager will be run on logging in to the backend. + | It's recommended to set this value to 'null' in production enviroments + | because it clears the cache every time a user logs in to the backend. + | If set to null, this setting is enabled when debug mode (app.debug) is enabled + | and disabled when debug mode is disabled. + | + */ + + 'runMigrationsOnLogin' => null, + + /* + |-------------------------------------------------------------------------- + | Determines which modules to load + |-------------------------------------------------------------------------- + | + | Specify which modules should be registered when using the application. + | + */ + + 'loadModules' => [ + 'System', + 'Backend', + 'Cms', + ], + + /* + |-------------------------------------------------------------------------- + | Prevents application updates + |-------------------------------------------------------------------------- + | + | If using composer or git to download updates to the core files, set this + | value to 'true' to prevent the update gateway from trying to download + | these files again as part of the application update process. Plugins + | and themes will still be downloaded. + | + */ + + 'disableCoreUpdates' => false, + + /* + |-------------------------------------------------------------------------- + | Specific plugins to disable + |-------------------------------------------------------------------------- + | + | Specify plugin codes which will always be disabled in the application. + | + */ + + 'disablePlugins' => [], + + /* + |-------------------------------------------------------------------------- + | Determines if the routing caching is enabled. + |-------------------------------------------------------------------------- + | + | If the caching is enabled, the page URL map is saved in the cache. If a page + | URL was changed on the disk, the old URL value could be still saved in the cache. + | To update the cache the back-end Clear Cache feature should be used. It is recommended + | to disable the caching during the development, and enable it in the production mode. + | + */ + + 'enableRoutesCache' => env('ROUTES_CACHE', false), + + /* + |-------------------------------------------------------------------------- + | Time to live for the URL map. + |-------------------------------------------------------------------------- + | + | The URL map used in the CMS page routing process. By default + | the map is updated every time when a page is saved in the back-end or when the + | interval, in minutes, specified with the urlMapCacheTTL parameter expires. + | + */ + + 'urlCacheTtl' => 10, + + /* + |-------------------------------------------------------------------------- + | Time to live for parsed CMS objects. + |-------------------------------------------------------------------------- + | + | Specifies the number of minutes the CMS object cache lives. After the interval + | is expired item are re-cached. Note that items are re-cached automatically when + | the corresponding template file is modified. + | + */ + + 'parsedPageCacheTTL' => 10, + + /* + |-------------------------------------------------------------------------- + | Determines if the asset caching is enabled. + |-------------------------------------------------------------------------- + | + | If the caching is enabled, combined assets are cached. If a asset file + | is changed on the disk, the old file contents could be still saved in the cache. + | To update the cache the back-end Clear Cache feature should be used. It is recommended + | to disable the caching during the development, and enable it in the production mode. + | + */ + + 'enableAssetCache' => env('ASSET_CACHE', false), + + /* + |-------------------------------------------------------------------------- + | Determines if the asset minification is enabled. + |-------------------------------------------------------------------------- + | + | If the minification is enabled, combined assets are compressed (minified). + | It is recommended to disable the minification during development, and + | enable it in production mode. If set to null, assets are minified + | when debug mode (app.debug) is disabled. + | + */ + + 'enableAssetMinify' => null, + + /* + |-------------------------------------------------------------------------- + | Check import timestamps when combining assets + |-------------------------------------------------------------------------- + | + | If deep hashing is enabled, the combiner cache will be reset when a change + | is detected on imported files, in addition to those referenced directly. + | This will cause slower page performance. If set to null, deep hashing + | is used when debug mode (app.debug) is enabled. + | + */ + + 'enableAssetDeepHashing' => null, + + /* + |-------------------------------------------------------------------------- + | Database-driven Themes + |-------------------------------------------------------------------------- + | + | Stores theme templates in the database instead of the filesystem. + | + | false - All theme templates are sourced from the filesystem. + | + | true - Source theme templates from the database with fallback to the filesytem. + | + | null - Setting equal to the inverse of app.debug: debug enabled, this disabled. + | + | The database layer stores all modified CMS files in the database. Files that are + | not modified continue to be loaded from the filesystem. The `theme:sync $themeDir` + | console command is available to populate the database from the filesystem with + | the `--toFile` flag to sync in the other direction (database to filesystem) and + | the `--paths="/path/to/file.md,/path/to/file2.md" flag to sync only specific files. + | + | Files modified in the database are cached to indicate that they should be loaded + | from the database. + | + */ + + 'databaseTemplates' => env('DATABASE_TEMPLATES', false), + + /* + |-------------------------------------------------------------------------- + | Public plugins path + |-------------------------------------------------------------------------- + | + | Specifies the public plugins path relative to the application base URL, + | or you can specify a full URL path. + | + */ + + 'pluginsPath' => '/plugins', + + /* + |-------------------------------------------------------------------------- + | Public themes path + |-------------------------------------------------------------------------- + | + | Specifies the public themes path relative to the application base URL, + | or you can specify a full URL path. + | + */ + + 'themesPath' => '/themes', + + /* + |-------------------------------------------------------------------------- + | Resource storage + |-------------------------------------------------------------------------- + | + | Specifies the configuration for resource storage, such as media and + | upload files. These resources are used: + | + | media - generated by the media manager. + | uploads - generated by attachment model relationships. + | resized - generated by System\Classes\ImageResizer or the resize() Twig filter + | + | For each resource you can specify: + | + | disk - filesystem disk, as specified in filesystems.php config. + | folder - a folder prefix for storing all generated files inside. + | path - the public path relative to the application base URL, + | or you can specify a full URL path. + | + | Optionally, you can specify how long temporary URLs to protected files + | in cloud storage (ex. AWS, RackSpace) are valid for by setting + | temporaryUrlTTL to a value in seconds to define a validity period. This + | is only used for the 'uploads' config when using a supported cloud disk + | + | NOTE: If you have installed Winter in a subfolder, are using local + | storage and are not using a linkPolicy of 'force' you should include + | the path to the subfolder in the `path` option for these storage + | configurations. + | + | Example: Winter is installed under https://localhost/projects/winter. + | You should then specify `/projects/winter/storage/app/uploads` as the + | path for the uploads disk and `/projects/winter/storage/app/media` as + | the path for the media disk. + */ + + 'storage' => [ + 'uploads' => [ + 'disk' => 'local', + 'folder' => 'uploads', + 'path' => '/storage/app/uploads', + 'temporaryUrlTTL' => 3600, + ], + 'media' => [ + 'disk' => 'local', + 'folder' => 'media', + 'path' => '/storage/app/media', + ], + 'resized' => [ + 'disk' => 'local', + 'folder' => 'resized', + 'path' => '/storage/app/resized', + ], + ], + + /* + |-------------------------------------------------------------------------- + | Convert Line Endings + |-------------------------------------------------------------------------- + | + | Determines if Winter should convert line endings from the windows style + | \r\n to the unix style \n. + | + */ + + 'convertLineEndings' => false, + + /* + |-------------------------------------------------------------------------- + | Linking policy + |-------------------------------------------------------------------------- + | + | Controls how URL links are generated throughout the application. + | + | detect - detect hostname and use the current schema + | secure - detect hostname and force HTTPS schema + | insecure - detect hostname and force HTTP schema + | force - force hostname and schema using app.url config value + | + | NOTE: force will ensure that the app.url value is used as the host for + | urls generated through the URL helpers which might have unintended + | consequences for projects that support multiple hostnames. + | + */ + + 'linkPolicy' => env('LINK_POLICY', 'detect'), + + /* + |-------------------------------------------------------------------------- + | Default permission mask + |-------------------------------------------------------------------------- + | + | Specifies a default file and folder permission for newly created objects. + | + */ + + 'defaultMask' => [ + 'file' => null, + 'folder' => null, + ], + + /* + |-------------------------------------------------------------------------- + | Safe mode + |-------------------------------------------------------------------------- + | + | If safe mode is enabled, the PHP code section is disabled in the CMS + | for security reasons. If set to null, safe mode is enabled when + | debug mode (app.debug) is disabled. + | + */ + + 'enableSafeMode' => null, + + /* + |-------------------------------------------------------------------------- + | Cross Site Request Forgery (CSRF) Protection + |-------------------------------------------------------------------------- + | + | If the CSRF protection is enabled, all "postback" & AJAX requests are + | checked for a valid security token. + | + */ + + 'enableCsrfProtection' => env('ENABLE_CSRF', true), + + /* + |-------------------------------------------------------------------------- + | Force bytecode invalidation + |-------------------------------------------------------------------------- + | + | When using OPcache with opcache.validate_timestamps set to 0 or APC + | with apc.stat set to 0 and Twig cache enabled, clearing the template + | cache won't update the cache, set to true to get around this. + | + */ + + 'forceBytecodeInvalidation' => true, + + /* + |-------------------------------------------------------------------------- + | Twig Strict Variables + |-------------------------------------------------------------------------- + | + | If strict_variables is disabled, Twig will silently ignore invalid + | variables (variables and or attributes/methods that do not exist) and + | replace them with a null value. When enabled, Twig throws an exception + | instead. If set to null, it is enabled when debug mode (app.debug) is + | enabled. + | + */ + + 'enableTwigStrictVariables' => false, + + /* + |-------------------------------------------------------------------------- + | Base Directory Restriction + |-------------------------------------------------------------------------- + | + | Restricts loading backend template and config files to within the base + | directory of the application. + | + | WARNING: This should always be enabled for security reasons. However, in + | some cases you may need to disable this; for instance when developing + | plugins that are stored elsewhere in the filesystem for organizational + | reasons and then symlinked into the application plugins/ directory. + | + | NEVER have this disabled in production. + | + */ + + 'restrictBaseDir' => env('RESTRICT_BASE_DIR', true), + + /* + |-------------------------------------------------------------------------- + | Backend Service Worker + |-------------------------------------------------------------------------- + | + | Allow plugins to run Service Workers in the backend. + | + | WARNING: This should always be disabled for security reasons as Service + | Workers can be hijacked and used to run XSS into the backend. Turning + | this feature on can create a conflict if you have a frontend Service + | Worker running. The 'scope' needs to be correctly set and not have a + | duplicate subfolder structure on the frontend, otherwise it will run + | on both the frontend and backend of your website. + | + | true - allow service workers to run in the backend + | + | false - disallow service workers to run in the backend + | + */ + + 'enableBackendServiceWorkers' => false, +]; diff --git a/config/cookie.php b/config/cookie.php new file mode 100644 index 0000000..654d29d --- /dev/null +++ b/config/cookie.php @@ -0,0 +1,20 @@ + [ + // 'my_cookie', + ], +]; diff --git a/config/cors.php b/config/cors.php new file mode 100644 index 0000000..6d9d75c --- /dev/null +++ b/config/cors.php @@ -0,0 +1,34 @@ + [], + + 'allowed_methods' => ['*'], + + 'allowed_origins' => ['*'], + + 'allowed_origins_patterns' => [], + + 'allowed_headers' => ['*'], + + 'exposed_headers' => [], + + 'max_age' => 0, + + 'supports_credentials' => false, + +]; diff --git a/config/database.php b/config/database.php new file mode 100644 index 0000000..f57e26a --- /dev/null +++ b/config/database.php @@ -0,0 +1,133 @@ + env('DB_CONNECTION', 'mysql'), + + /* + |-------------------------------------------------------------------------- + | Database Connections + |-------------------------------------------------------------------------- + | + | Here are each of the database connections setup for your application. + | Of course, examples of configuring each database platform that is + | supported by Winter CMS is shown below to make development simple. + | + | All database work in Winter CMS is done through the PHP PDO facilities + | so make sure you have the driver for your particular database of + | choice installed on your machine before you begin development. + | + */ + + 'connections' => [ + 'sqlite' => [ + 'database' => env('DB_DATABASE', storage_path('database.sqlite')), + 'driver' => 'sqlite', + 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), + 'prefix' => '', + 'url' => env('DATABASE_URL'), + ], + 'mysql' => [ + 'charset' => 'utf8mb4', + 'collation' => 'utf8mb4_unicode_ci', + 'database' => env('DB_DATABASE', 'winter'), + 'driver' => 'mysql', + 'engine' => 'InnoDB', + 'host' => env('DB_HOST', '127.0.0.1'), + 'options' => extension_loaded('pdo_mysql') ? array_filter([ + PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), + ]) : [], + 'password' => env('DB_PASSWORD', ''), + 'port' => env('DB_PORT', '3306'), + 'prefix' => '', + 'prefix_indexes' => true, + 'strict' => true, + 'unix_socket' => env('DB_SOCKET', ''), + 'url' => env('DATABASE_URL'), + 'username' => env('DB_USERNAME', 'winter'), + ], + 'pgsql' => [ + 'charset' => 'utf8', + 'database' => env('DB_DATABASE', 'winter'), + 'driver' => 'pgsql', + 'host' => env('DB_HOST', '127.0.0.1'), + 'password' => env('DB_PASSWORD', ''), + 'port' => env('DB_PORT', '5432'), + 'prefix' => '', + 'prefix_indexes' => true, + 'search_path' => 'public', + 'sslmode' => 'prefer', + 'url' => env('DATABASE_URL'), + 'username' => env('DB_USERNAME', 'winter'), + ], + 'sqlsrv' => [ + 'charset' => 'utf8', + 'database' => env('DB_DATABASE', 'winter'), + 'driver' => 'sqlsrv', + 'host' => env('DB_HOST', '127.0.0.1'), + 'password' => env('DB_PASSWORD', ''), + 'port' => env('DB_PORT', '1433'), + 'prefix' => '', + 'prefix_indexes' => true, + 'url' => env('DATABASE_URL'), + 'username' => env('DB_USERNAME', 'winter'), + ], + ], + + /* + |-------------------------------------------------------------------------- + | Migration Repository Table + |-------------------------------------------------------------------------- + | + | This table keeps track of all the migrations that have already run for + | your application. Using this information, we can determine which of + | the migrations on disk haven't actually been run in the database. + | + */ + + 'migrations' => 'migrations', + + /* + |-------------------------------------------------------------------------- + | Redis Databases + |-------------------------------------------------------------------------- + | + | Redis is an open source, fast, and advanced key-value store that also + | provides a richer body of commands than a typical key-value system + | such as APC or Memcached. Winter makes it easy to dig right in. + | + */ + + 'redis' => [ + 'client' => env('REDIS_CLIENT', 'phpredis'), + 'options' => [ + 'cluster' => env('REDIS_CLUSTER', 'redis'), + 'prefix' => env('REDIS_PREFIX', str_slug(env('APP_NAME', 'winter'), '_') . '_database_'), + ], + 'default' => [ + 'database' => env('REDIS_DB', '0'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'url' => env('REDIS_URL'), + ], + 'cache' => [ + 'database' => env('REDIS_CACHE_DB', '1'), + 'host' => env('REDIS_HOST', '127.0.0.1'), + 'password' => env('REDIS_PASSWORD'), + 'port' => env('REDIS_PORT', '6379'), + 'url' => env('REDIS_URL'), + ], + ], +]; diff --git a/config/dev/.gitignore b/config/dev/.gitignore new file mode 100644 index 0000000..c96a04f --- /dev/null +++ b/config/dev/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/config/develop.php b/config/develop.php new file mode 100644 index 0000000..2d31619 --- /dev/null +++ b/config/develop.php @@ -0,0 +1,58 @@ + false, + + /* + |-------------------------------------------------------------------------- + | Allow deep-level symlinks + |-------------------------------------------------------------------------- + | + | Winter CMS, by default, will allow symlinks within the first level of + | subdirectories. When this feature is enabled, the system will allow + | symlinks to be used at any directory level. This can be useful for + | symlinking individual plugins or themes. + | + | Please note that this has a negative effect on performance. This feature + | abides by "cms.restrictBaseDir" - if enabled, symlinks cannot point to + | resources outside of the root folder. + | + | true - allow symlinks at any level + | + | false - only allow symlinks at the first level of subdirectories (default) + | + */ + + 'allowDeepSymlinks' => false, + + /* + |-------------------------------------------------------------------------- + | Enable Snowboard debugging + |-------------------------------------------------------------------------- + | + | By default, Snowboard debugging and client-side logging is disabled. + | + | If you wish to enable Snowboard debugging, set this value to `true`. + | + */ + + 'debugSnowboard' => env('DEBUG_SNOWBOARD', false), +]; diff --git a/config/environment.php b/config/environment.php new file mode 100644 index 0000000..caa9f65 --- /dev/null +++ b/config/environment.php @@ -0,0 +1,32 @@ + 'development', + + /* + |-------------------------------------------------------------------------- + | Environment Multitenancy + |-------------------------------------------------------------------------- + | + | You may specify a different environment according to the hostname that + | is provided with the HTTP request. This is useful if you want to use + | different configuration, such as database and theme, per hostname. + | + */ + + 'hosts' => [ + 'localhost' => 'dev', + ], +]; diff --git a/config/filesystems.php b/config/filesystems.php new file mode 100644 index 0000000..64cd176 --- /dev/null +++ b/config/filesystems.php @@ -0,0 +1,53 @@ + env('FILESYSTEM_DISK', 'local'), + + /* + |-------------------------------------------------------------------------- + | Filesystem Disks + |-------------------------------------------------------------------------- + | + | Here you may configure as many filesystem "disks" as you wish, and you + | may even configure multiple disks of the same driver. Defaults have + | been setup for each driver as an example of the required options. + | + | Supported Drivers: "local", "ftp", "sftp", "s3" + | + | NOTE: s3's stream_uploads option requires the Winter.DriverAWS plugin + | to be installed and enabled. + | + */ + + 'disks' => [ + 'local' => [ + 'driver' => 'local', + 'root' => storage_path('app'), + 'url' => '/storage/app', + 'visibility' => 'public', + ], + 's3' => [ + 'bucket' => env('AWS_BUCKET'), + 'driver' => 's3', + 'endpoint' => env('AWS_ENDPOINT'), + 'key' => env('AWS_ACCESS_KEY_ID'), + 'region' => env('AWS_DEFAULT_REGION'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'stream_uploads' => env('AWS_S3_STREAM_UPLOADS', false), + 'url' => env('AWS_URL'), + 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), + ], + ], +]; diff --git a/config/hashing.php b/config/hashing.php new file mode 100644 index 0000000..ad56664 --- /dev/null +++ b/config/hashing.php @@ -0,0 +1,51 @@ + 'bcrypt', + + /* + |-------------------------------------------------------------------------- + | Bcrypt Options + |-------------------------------------------------------------------------- + | + | Here you may specify the configuration options that should be used when + | passwords are hashed using the Bcrypt algorithm. This will allow you + | to control the amount of time it takes to hash the given password. + | + */ + + 'bcrypt' => [ + 'rounds' => env('BCRYPT_ROUNDS', 10), + ], + + /* + |-------------------------------------------------------------------------- + | Argon Options + |-------------------------------------------------------------------------- + | + | Here you may specify the configuration options that should be used when + | passwords are hashed using the Argon algorithm. These will allow you + | to control the amount of time it takes to hash the given password. + | + */ + + 'argon' => [ + 'memory' => 65536, + 'threads' => 1, + 'time' => 4, + ], +]; diff --git a/config/logging.php b/config/logging.php new file mode 100644 index 0000000..415941e --- /dev/null +++ b/config/logging.php @@ -0,0 +1,107 @@ + env('LOG_CHANNEL', 'stack'), + + /* + |-------------------------------------------------------------------------- + | Deprecations Log Channel + |-------------------------------------------------------------------------- + | + | This option controls the log channel that should be used to log warnings + | regarding deprecated PHP and library features. This allows you to get + | your application ready for upcoming major versions of dependencies. + | + */ + + 'deprecations' => env('LOG_DEPRECATIONS_CHANNEL', 'null'), + + /* + |-------------------------------------------------------------------------- + | Log Channels + |-------------------------------------------------------------------------- + | + | Here you may configure the log channels for your application. Out of + | the box, Winter uses the Monolog PHP logging library. This gives + | you a variety of powerful log handlers / formatters to utilize. + | + | Available Drivers: "single", "daily", "slack", "syslog", + | "errorlog", "monolog", + | "custom", "stack" + | + */ + + 'channels' => [ + 'stack' => [ + 'channels' => [ + 'single', + ], + 'driver' => 'stack', + 'ignore_exceptions' => false, + ], + 'single' => [ + 'driver' => 'single', + 'level' => env('LOG_LEVEL', 'debug'), + 'path' => storage_path('logs/system.log'), + ], + 'daily' => [ + 'days' => 14, + 'driver' => 'daily', + 'level' => env('LOG_LEVEL', 'debug'), + 'path' => storage_path('logs/system.log'), + ], + 'slack' => [ + 'driver' => 'slack', + 'emoji' => ':boom:', + 'level' => env('LOG_LEVEL', 'critical'), + 'url' => env('LOG_SLACK_WEBHOOK_URL'), + 'username' => 'Winter Log', + ], + 'papertrail' => [ + 'driver' => 'monolog', + 'handler' => env('LOG_PAPERTRAIL_HANDLER', \Monolog\Handler\SyslogUdpHandler::class), + 'handler_with' => [ + 'connectionString' => 'tls://' . env('PAPERTRAIL_URL') . ':' . env('PAPERTRAIL_PORT'), + 'host' => env('PAPERTRAIL_URL'), + 'port' => env('PAPERTRAIL_PORT'), + ], + 'level' => env('LOG_LEVEL', 'debug'), + ], + 'stderr' => [ + 'driver' => 'monolog', + 'formatter' => env('LOG_STDERR_FORMATTER'), + 'handler' => \Monolog\Handler\StreamHandler::class, + 'level' => env('LOG_LEVEL', 'debug'), + 'with' => [ + 'stream' => 'php://stderr', + ], + ], + 'syslog' => [ + 'driver' => 'syslog', + 'level' => env('LOG_LEVEL', 'debug'), + ], + 'errorlog' => [ + 'driver' => 'errorlog', + 'level' => env('LOG_LEVEL', 'debug'), + ], + 'null' => [ + 'driver' => 'monolog', + 'handler' => \Monolog\Handler\NullHandler::class, + ], + 'emergency' => [ + 'path' => storage_path('logs/system.log'), + ], + ], +]; diff --git a/config/mail.php b/config/mail.php new file mode 100644 index 0000000..a297c11 --- /dev/null +++ b/config/mail.php @@ -0,0 +1,92 @@ + env('MAIL_MAILER', 'smtp'), + + /* + |-------------------------------------------------------------------------- + | Mailer Configurations + |-------------------------------------------------------------------------- + | + | Here you may configure all of the mailers used by your application plus + | their respective settings. Several examples have been configured for + | you and you are free to add your own as your application requires. + | + | Winter supports a variety of mail "transport" drivers to be used while + | sending an e-mail. You will specify which one you are using for your + | mailers below. You are free to add additional mailers as required. + | + | Supported: "smtp", "sendmail", "mailgun", "ses", + | "postmark", "log", "array", "failover" + | + */ + + 'mailers' => [ + 'smtp' => [ + 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), + 'password' => env('MAIL_PASSWORD'), + 'port' => env('MAIL_PORT', 587), + 'timeout' => null, + 'transport' => 'smtp', + 'username' => env('MAIL_USERNAME'), + ], + 'ses' => [ + 'transport' => 'ses', + ], + 'mailgun' => [ + 'transport' => 'mailgun', + ], + 'postmark' => [ + 'transport' => 'postmark', + ], + 'mail' => [ + 'transport' => 'mail', + ], + 'sendmail' => [ + 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -t -i'), + 'transport' => 'sendmail', + ], + 'log' => [ + 'channel' => env('MAIL_LOG_CHANNEL'), + 'transport' => 'log', + ], + 'array' => [ + 'transport' => 'array', + ], + 'failover' => [ + 'mailers' => [ + 'smtp', + 'log', + ], + 'transport' => 'failover', + ], + ], + + /* + |-------------------------------------------------------------------------- + | Global "From" Address + |-------------------------------------------------------------------------- + | + | You may wish for all e-mails sent by your application to be sent from + | the same address. Here, you may specify a name and address that is + | used globally for all e-mails that are sent by your application. + | + */ + + 'from' => [ + 'address' => env('MAIL_FROM_ADDRESS', 'noreply@example.com'), + 'name' => env('MAIL_FROM_NAME', env('APP_NAME', 'Winter CMS')), + ], +]; diff --git a/config/queue.php b/config/queue.php new file mode 100644 index 0000000..7115084 --- /dev/null +++ b/config/queue.php @@ -0,0 +1,102 @@ + env('QUEUE_CONNECTION', 'sync'), + + /* + |-------------------------------------------------------------------------- + | Queue Connections + |-------------------------------------------------------------------------- + | + | Here you may configure the connection information for each server that + | is used by your application. A default configuration has been added + | for each back-end shipped with Winter. You are free to add more. + | + | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" + | + */ + + 'connections' => [ + 'sync' => [ + 'driver' => 'sync', + ], + 'database' => [ + 'after_commit' => false, + 'driver' => 'database', + 'queue' => 'default', + 'retry_after' => 90, + 'table' => 'jobs', + ], + 'beanstalkd' => [ + 'after_commit' => false, + 'block_for' => 0, + 'driver' => 'beanstalkd', + 'host' => 'localhost', + 'queue' => 'default', + 'retry_after' => 90, + ], + 'sqs' => [ + 'after_commit' => false, + 'driver' => 'sqs', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), + 'queue' => env('SQS_QUEUE', 'default'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'suffix' => env('SQS_SUFFIX'), + ], + 'redis' => [ + 'after_commit' => false, + 'block_for' => null, + 'connection' => 'default', + 'driver' => 'redis', + 'queue' => env('REDIS_QUEUE', 'default'), + 'retry_after' => 90, + ], + ], + + /* + |-------------------------------------------------------------------------- + | Job Batching + |-------------------------------------------------------------------------- + | + | The following options configure the database and table that store job + | batching information. These options can be updated to any database + | connection and table which has been defined by your application. + | + */ + + 'batching' => [ + 'database' => env('DB_CONNECTION', 'mysql'), + 'table' => 'job_batches', + ], + + /* + |-------------------------------------------------------------------------- + | Failed Queue Jobs + |-------------------------------------------------------------------------- + | + | These options configure the behavior of failed queue job logging so you + | can control which database and table are used to store the jobs that + | have failed. You may change them to any database / table you wish. + | + */ + + 'failed' => [ + 'database' => env('DB_CONNECTION', 'mysql'), + 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'), + 'table' => 'failed_jobs', + ], +]; diff --git a/config/services.php b/config/services.php new file mode 100644 index 0000000..fd9b6e0 --- /dev/null +++ b/config/services.php @@ -0,0 +1,30 @@ + [ + 'domain' => env('MAILGUN_DOMAIN'), + 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), + 'secret' => env('MAILGUN_SECRET'), + ], + 'postmark' => [ + 'token' => env('POSTMARK_TOKEN'), + ], + 'ses' => [ + 'key' => env('AWS_ACCESS_KEY_ID'), + 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + ], +]; diff --git a/config/session.php b/config/session.php new file mode 100644 index 0000000..2137951 --- /dev/null +++ b/config/session.php @@ -0,0 +1,216 @@ + env('SESSION_DRIVER', 'file'), + + /* + |-------------------------------------------------------------------------- + | Session Lifetime + |-------------------------------------------------------------------------- + | + | Here you may specify the number of minutes that you wish the session + | to be allowed to remain idle before it expires. If you want them + | to immediately expire on the browser closing, set that option. + | + */ + + 'lifetime' => env('SESSION_LIFETIME', 120), + 'expire_on_close' => false, + + /* + |-------------------------------------------------------------------------- + | Session Encryption + |-------------------------------------------------------------------------- + | + | This option allows you to easily specify that all of your session data + | should be encrypted before it is stored. All encryption will be run + | automatically by Laravel and you can use the Session like normal. + | + */ + + 'encrypt' => false, + + /* + |-------------------------------------------------------------------------- + | Session File Location + |-------------------------------------------------------------------------- + | + | When using the native session driver, we need a location where session + | files may be stored. A default has been set for you but a different + | location may be specified. This is only needed for file sessions. + | + */ + + 'files' => storage_path('framework/sessions'), + + /* + |-------------------------------------------------------------------------- + | Session Database Connection + |-------------------------------------------------------------------------- + | + | When using the "database" or "redis" session drivers, you may specify a + | connection that should be used to manage these sessions. This should + | correspond to a connection in your database configuration options. + | + */ + + 'connection' => env('SESSION_CONNECTION'), + + /* + |-------------------------------------------------------------------------- + | Session Database Table + |-------------------------------------------------------------------------- + | + | When using the "database" session driver, you may specify the table we + | should use to manage the sessions. Of course, a sensible default is + | provided for you; however, you are free to change this as needed. + | + */ + + 'table' => 'sessions', + + /* + |-------------------------------------------------------------------------- + | Session Cache Store + |-------------------------------------------------------------------------- + | + | While using one of the framework's cache driven session backends you may + | list a cache store that should be used for these sessions. This value + | must match with one of the application's configured cache "stores". + | + | Affects: "apc", "dynamodb", "memcached", "redis" + | + */ + + 'store' => env('SESSION_STORE'), + + /* + |-------------------------------------------------------------------------- + | Session Sweeping Lottery + |-------------------------------------------------------------------------- + | + | Some session drivers must manually sweep their storage location to get + | rid of old sessions from storage. Here are the chances that it will + | happen on a given request. By default, the odds are 2 out of 100. + | + */ + + 'lottery' => [ + 2, + 100, + ], + + /* + |-------------------------------------------------------------------------- + | Session Cookie Name + |-------------------------------------------------------------------------- + | + | Here you may change the name of the cookie used to identify a session + | instance by ID. The name specified here will get used every time a + | new session cookie is created by the framework for every driver. + | + */ + + 'cookie' => env('SESSION_COOKIE', str_slug(env('APP_NAME', 'winter'), '_') . '_session'), + + /* + |-------------------------------------------------------------------------- + | Session Cookie Path + |-------------------------------------------------------------------------- + | + | The session cookie path determines the path for which the cookie will + | be regarded as available. Typically, this will be the root path of + | your application but you are free to change this when necessary. + | + */ + + 'path' => '/', + + /* + |-------------------------------------------------------------------------- + | Session Cookie Domain + |-------------------------------------------------------------------------- + | + | Here you may change the domain of the cookie used to identify a session + | in your application. This will determine which domains the cookie is + | available to in your application. A sensible default has been set. + | + */ + + 'domain' => env('SESSION_DOMAIN'), + + /* + |-------------------------------------------------------------------------- + | HTTP Access Only + |-------------------------------------------------------------------------- + | + | Setting this value to true will prevent JavaScript from accessing the + | value of the cookie and the cookie will only be accessible through + | the HTTP protocol. You are free to modify this option if needed. + | + */ + + 'http_only' => true, + + /* + |-------------------------------------------------------------------------- + | HTTPS Only Cookies + |-------------------------------------------------------------------------- + | + | By setting this option to true, session cookies will only be sent back + | to the server if the browser has a HTTPS connection. This will keep + | the cookie from being sent to you when it can't be done securely. + | + */ + + 'secure' => env('SESSION_SECURE_COOKIE', false), + + /* + |-------------------------------------------------------------------------- + | Same-Site Cookies + |-------------------------------------------------------------------------- + | + | This option determines how your cookies behave when cross-site requests + | take place, and can be used to mitigate CSRF attacks. By default, we + | will set this value to "lax" since this is a secure default value. + | + | Cookies that match the domain of the current site, i.e. what's displayed + | in the browser's address bar, are referred to as first-party cookies. + | Similarly, cookies from domains other than the current site are referred + | to as third-party cookies. + | + | Cookies without a SameSite attribute will be treated as `SameSite=lax`, + | meaning the default behaviour will be to restrict cookies to first party + | contexts only. + | + | Cookies for cross-site usage must specify `same_site` as 'None' and `secure` + | as `true` to work correctly. + | + | lax - Cookies are allowed to be sent with top-level navigations and will + | be sent along with GET request initiated by third party website. + | This is the default value in modern browsers. + | + | strict - Cookies will only be sent in a first-party context and not be + | sent along with requests initiated by third party websites. + | + | Supported: "lax", "strict", "none", null + | + */ + + 'same_site' => 'lax', +]; diff --git a/config/testing/cms.php b/config/testing/cms.php new file mode 100644 index 0000000..f8660bb --- /dev/null +++ b/config/testing/cms.php @@ -0,0 +1,182 @@ + 'test', + + /* + |-------------------------------------------------------------------------- + | Time to live for parsed CMS objects. + |-------------------------------------------------------------------------- + | + | Specifies the number of minutes the CMS object cache lives. After the interval + | is expired item are re-cached. Note that items are re-cached automatically when + | the corresponding template file is modified. + | + */ + + 'parsedPageCacheTTL' => 1440, + + /* + |-------------------------------------------------------------------------- + | Determines if the routing caching is enabled. + |-------------------------------------------------------------------------- + | + | If the caching is enabled, the page URL map is saved in the cache. If a page + | URL was changed on the disk, the old URL value could be still saved in the cache. + | To update the cache the back-end Clear Cache feature should be used. It is recommended + | to disable the caching during the development, and enable it in the production mode. + | + */ + + 'enableRoutesCache' => true, + + /* + |-------------------------------------------------------------------------- + | Time to live for the URL map. + |-------------------------------------------------------------------------- + | + | The URL map used in the CMS page routing process. By default + | the map is updated every time when a page is saved in the back-end or when the + | interval, in minutes, specified with the urlMapCacheTTL parameter expires. + | + */ + + 'urlCacheTtl' => 1, + + /* + |-------------------------------------------------------------------------- + | Determines if the asset caching is enabled. + |-------------------------------------------------------------------------- + | + | If the caching is enabled, combined assets are cached. If a asset file + | is changed on the disk, the old file contents could be still saved in the cache. + | To update the cache the back-end Clear Cache feature should be used. It is recommended + | to disable the caching during the development, and enable it in the production mode. + | + */ + + 'enableAssetCache' => false, + + /* + |-------------------------------------------------------------------------- + | Disables Twig caching for unit tests + |-------------------------------------------------------------------------- + */ + + 'twigNoCache' => true, + + /* + |-------------------------------------------------------------------------- + | Convert Line Endings + |-------------------------------------------------------------------------- + | + | Determines if Winter should convert line endings from the windows style + | \r\n to the unix style \n. + | + */ + + 'convertLineEndings' => true, + + /* + |-------------------------------------------------------------------------- + | Local plugins path + |-------------------------------------------------------------------------- + | + | Specifies the absolute local plugins path. + | + */ + + 'pluginsPathLocal' => base_path('modules/system/tests/fixtures/plugins'), + + /* + |-------------------------------------------------------------------------- + | Local themes path + |-------------------------------------------------------------------------- + | + | Specifies the absolute local themes path. + | + */ + + 'themesPathLocal' => base_path('modules/cms/tests/fixtures/themes'), + + /* + |-------------------------------------------------------------------------- + | Resource storage + |-------------------------------------------------------------------------- + | + | Specifies the configuration for resource storage, such as media and + | upload files. These resources are used: + | + | media - generated by the media manager. + | uploads - generated by attachment model relationships. + | resized - generated by System\Classes\ImageResizer or the resize() Twig filter + | + | For each resource you can specify: + | + | disk - filesystem disk, as specified in filesystems.php config. + | folder - a folder prefix for storing all generated files inside. + | path - the public path relative to the application base URL, + | or you can specify a full URL path. + | + | Optionally, you can specify how long temporary URLs to protected files + | in cloud storage (ex. AWS, RackSpace) are valid for by setting + | temporaryUrlTTL to a value in seconds to define a validity period. This + | is only used for the 'uploads' config when using a supported cloud disk + | + | NOTE: If you have installed Winter in a subfolder, are using local + | storage and are not using a linkPolicy of 'force' you should include + | the path to the subfolder in the `path` option for these storage + | configurations. + | + | Example: Winter is installed under https://localhost/projects/winter. + | You should then specify `/projects/winter/storage/app/uploads` as the + | path for the uploads disk and `/projects/winter/storage/app/media` as + | the path for the media disk. + */ + + 'storage' => [ + + 'uploads' => [ + 'disk' => 'local', + 'folder' => 'uploads', + 'path' => '/storage/tests/app/uploads', + 'temporaryUrlTTL' => 3600, + ], + + 'media' => [ + 'disk' => 'local', + 'folder' => 'media', + 'path' => '/storage/tests/app/media', + ], + + 'resized' => [ + 'disk' => 'local', + 'folder' => 'resized', + 'path' => '/storage/tests/app/resized', + ], + + ], + + /* + |-------------------------------------------------------------------------- + | Cross Site Request Forgery (CSRF) Protection + |-------------------------------------------------------------------------- + | + | If the CSRF protection is enabled, all "postback" requests are checked + | for a valid security token. + | + */ + + 'enableCsrfProtection' => false, + +]; diff --git a/config/testing/filesystems.php b/config/testing/filesystems.php new file mode 100644 index 0000000..d7bf8bf --- /dev/null +++ b/config/testing/filesystems.php @@ -0,0 +1,64 @@ + 'local', + + /* + |-------------------------------------------------------------------------- + | Default Cloud Filesystem Disk + |-------------------------------------------------------------------------- + | + | Many applications store files both locally and in the cloud. For this + | reason, you may specify a default "cloud" driver here. This driver + | will be bound as the Cloud disk implementation in the container. + | + */ + + 'cloud' => 's3', + + /* + |-------------------------------------------------------------------------- + | Filesystem Disks + |-------------------------------------------------------------------------- + | + | Here you may configure as many filesystem "disks" as you wish, and you + | may even configure multiple disks of the same driver. Defaults have + | been setup for each driver as an example of the required options. + | + | Supported Drivers: "local", "ftp", "sftp", "s3" + | + */ + + 'disks' => [ + + 'local' => [ + 'driver' => 'local', + 'root' => base_path('storage/tests/app'), + 'url' => '/storage/tests/app', + ], + + 's3' => [ + 'driver' => 's3', + 'key' => '', + 'secret' => '', + 'region' => '', + 'bucket' => '', + // 'url' => env('AWS_URL'), + // 'endpoint' => env('AWS_ENDPOINT'), + ], + + ], + +]; diff --git a/config/view.php b/config/view.php new file mode 100644 index 0000000..63394f6 --- /dev/null +++ b/config/view.php @@ -0,0 +1,34 @@ + [ + // Default Laravel Blade template location + // @see https://github.com/octobercms/october/issues/3473 & https://github.com/octobercms/october/issues/3459 + // realpath(base_path('resources/views')) + ], + + /* + |-------------------------------------------------------------------------- + | Compiled View Path + |-------------------------------------------------------------------------- + | + | This option determines where all the compiled Blade templates will be + | stored for your application. Typically, this is within the storage + | directory. However, as usual, you are free to change this value. + | + */ + + 'compiled' => env('VIEW_COMPILED_PATH', realpath(storage_path('framework/views'))), +]; diff --git a/index.php b/index.php new file mode 100644 index 0000000..3ce7b10 --- /dev/null +++ b/index.php @@ -0,0 +1,48 @@ +make(Illuminate\Contracts\Http\Kernel::class); + +$response = $kernel->handle( + $request = Illuminate\Http\Request::capture() +); + +$response->send(); + +$kernel->terminate($request, $response); diff --git a/modules/backend/.eslintignore b/modules/backend/.eslintignore new file mode 100644 index 0000000..b84f862 --- /dev/null +++ b/modules/backend/.eslintignore @@ -0,0 +1,17 @@ +# Ignore build files +**/node_modules/** +build/*.js +**/build/*.js +**/mix.webpack.js + +# Ignore all JS except for Mix-based assets +assets/js +assets/vendor +behaviors/**/*.js +controllers/**/*.js +formwidgets/**/*.js +reportwidgets/**/*.js +widgets/**/*.js + +# Ignore test fixtures +tests diff --git a/modules/backend/.eslintrc.json b/modules/backend/.eslintrc.json new file mode 100644 index 0000000..c625599 --- /dev/null +++ b/modules/backend/.eslintrc.json @@ -0,0 +1,45 @@ +{ + "env": { + "es6": true, + "browser": true + }, + "globals": { + "Snowboard": "writable" + }, + "extends": [ + "airbnb-base", + "plugin:vue/vue3-recommended" + ], + "ignorePatterns": [ + "assets/js", + "assets/vendor", + "behaviors/**/*.js", + "controllers/**/*.js", + "formwidgets/**/*.js", + "reportwidgets/**/*.js", + "widgets/**/*.js" + ], + "rules": { + "class-methods-use-this": ["off"], + "indent": ["error", 4, { + "SwitchCase": 1 + }], + "max-len": ["off"], + "new-cap": ["error", { "properties": false }], + "no-alert": ["off"], + "no-param-reassign": ["error", { + "props": false + }], + "vue/html-indent": ["error", 4], + "vue/html-self-closing": ["error", { + "html": { + "void": "never", + "normal": "any", + "component": "always" + }, + "svg": "always", + "math": "always" + }], + "vue/multi-word-component-names": ["off"] + } +} diff --git a/modules/backend/.gitignore b/modules/backend/.gitignore new file mode 100644 index 0000000..e75539d --- /dev/null +++ b/modules/backend/.gitignore @@ -0,0 +1,6 @@ +# Backend module ignores + +# Ignore Mix files +node_modules +package-lock.json +mix.webpack.js diff --git a/modules/backend/LICENSE b/modules/backend/LICENSE new file mode 100644 index 0000000..7b47a3b --- /dev/null +++ b/modules/backend/LICENSE @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2013-2021.03.01 October CMS +Copyright (c) 2021 Winter CMS + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/modules/backend/README.md b/modules/backend/README.md new file mode 100644 index 0000000..bce0dcf --- /dev/null +++ b/modules/backend/README.md @@ -0,0 +1,5 @@ +# Winter CMS - Backend Module + +This repository is a read-only sub-split of the Winter CMS `Backend` module for use in Composer. Please note that we do not accept any pull requests to this repository. + +If you wish to make changes to this module, please submit them to the [main repository](https://github.com/wintercms/winter). diff --git a/modules/backend/ServiceProvider.php b/modules/backend/ServiceProvider.php new file mode 100644 index 0000000..9ff5e50 --- /dev/null +++ b/modules/backend/ServiceProvider.php @@ -0,0 +1,338 @@ +registerConsole(); + $this->registerMailer(); + $this->registerBackendPermissions(); + $this->registerBackendUserEvents(); + + /* + * Backend specific + */ + if ($this->app->runningInBackend()) { + $this->registerBackendNavigation(); + $this->registerBackendReportWidgets(); + $this->registerBackendWidgets(); + $this->registerBackendSettings(); + } + } + + /** + * Bootstrap the module events. + * + * @return void + */ + public function boot() + { + $this->registerAssetBundles(); + parent::boot('backend'); + } + + /** + * Register console commands + */ + protected function registerConsole() + { + $this->registerConsoleCommand('create.controller', \Backend\Console\CreateController::class); + $this->registerConsoleCommand('create.formwidget', \Backend\Console\CreateFormWidget::class); + $this->registerConsoleCommand('create.reportwidget', \Backend\Console\CreateReportWidget::class); + $this->registerConsoleCommand('user.create', \Backend\Console\UserCreate::class); + $this->registerConsoleCommand('winter.passwd', \Backend\Console\WinterPasswd::class); + } + + /** + * Register mail templates + */ + protected function registerMailer() + { + MailManager::instance()->registerCallback(function ($manager) { + $manager->registerMailTemplates([ + 'backend::mail.invite', + 'backend::mail.restore', + ]); + }); + } + + /** + * Register asset bundles + */ + protected function registerAssetBundles() + { + CombineAssets::registerCallback(function ($combiner) { + $combiner->registerBundle('~/modules/backend/assets/less/winter.less'); + $combiner->registerBundle('~/modules/backend/assets/js/winter.js'); + $combiner->registerBundle('~/modules/backend/widgets/table/assets/js/build.js'); + $combiner->registerBundle('~/modules/backend/assets/vendor/ace-codeeditor/build.js'); + $combiner->registerBundle('~/modules/backend/widgets/mediamanager/assets/js/mediamanager-browser.js'); + $combiner->registerBundle('~/modules/backend/widgets/mediamanager/assets/less/mediamanager.less'); + $combiner->registerBundle('~/modules/backend/widgets/reportcontainer/assets/less/reportcontainer.less'); + $combiner->registerBundle('~/modules/backend/widgets/table/assets/less/table.less'); + $combiner->registerBundle('~/modules/backend/formwidgets/repeater/assets/less/repeater.less'); + $combiner->registerBundle('~/modules/backend/formwidgets/fieldset/assets/less/fieldset.less'); + $combiner->registerBundle('~/modules/backend/formwidgets/fileupload/assets/less/fileupload.less'); + $combiner->registerBundle('~/modules/backend/formwidgets/nestedform/assets/less/nestedform.less'); + $combiner->registerBundle('~/modules/backend/formwidgets/richeditor/assets/js/build-plugins.js'); + $combiner->registerBundle('~/modules/backend/formwidgets/permissioneditor/assets/less/permissioneditor.less'); + $combiner->registerBundle('~/modules/backend/formwidgets/markdowneditor/assets/less/markdowneditor.less'); + + /* + * Rich Editor is protected by DRM + */ + if (file_exists(base_path('modules/backend/formwidgets/richeditor/assets/vendor/froala_drm'))) { + $combiner->registerBundle('~/modules/backend/formwidgets/richeditor/assets/less/richeditor.less'); + $combiner->registerBundle('~/modules/backend/formwidgets/richeditor/assets/js/build.js'); + } + }); + + PackageManager::registerCallback(function ($mix) { + $mix->registerPackage('module-backend.formwidgets.codeeditor', '~/modules/backend/formwidgets/codeeditor/assets/winter.mix.js'); + }); + } + + /* + * Register navigation + */ + protected function registerBackendNavigation() + { + BackendMenu::registerCallback(function ($manager) { + $manager->registerMenuItems('Winter.Backend', [ + 'dashboard' => [ + 'label' => 'backend::lang.dashboard.menu_label', + 'icon' => 'icon-dashboard', + 'iconSvg' => 'modules/backend/assets/images/dashboard-icon.svg', + 'url' => Backend::url('backend'), + 'permissions' => ['backend.access_dashboard'], + 'order' => 10 + ], + 'media' => [ + 'label' => 'backend::lang.media.menu_label', + 'icon' => 'icon-folder', + 'iconSvg' => 'modules/backend/assets/images/media-icon.svg', + 'url' => Backend::url('backend/media'), + 'permissions' => ['media.*'], + 'order' => 200 + ] + ]); + $manager->registerOwnerAlias('Winter.Backend', 'October.Backend'); + }); + } + + /* + * Register report widgets + */ + protected function registerBackendReportWidgets() + { + WidgetManager::instance()->registerReportWidgets(function ($manager) { + $manager->registerReportWidget(\Backend\ReportWidgets\Welcome::class, [ + 'label' => 'backend::lang.dashboard.welcome.widget_title_default', + 'context' => 'dashboard' + ]); + }); + } + + /* + * Register permissions + */ + protected function registerBackendPermissions() + { + BackendAuth::registerCallback(function ($manager) { + $manager->registerPermissions('Winter.Backend', [ + 'backend.access_dashboard' => [ + 'label' => 'system::lang.permissions.view_the_dashboard', + 'tab' => 'system::lang.permissions.name', + 'roles' => [UserRole::CODE_DEVELOPER, UserRole::CODE_PUBLISHER], + ], + 'backend.manage_default_dashboard' => [ + 'label' => 'system::lang.permissions.manage_default_dashboard', + 'tab' => 'system::lang.permissions.name', + 'comment' => 'system::lang.permissions.manage_default_dashboard_comment', + 'roles' => [UserRole::CODE_DEVELOPER], + ], + 'backend.manage_users' => [ + 'label' => 'system::lang.permissions.manage_other_administrators', + 'tab' => 'system::lang.permissions.name', + 'comment' => 'system::lang.permissions.manage_other_administrators_comment', + 'roles' => [UserRole::CODE_DEVELOPER], + ], + 'backend.impersonate_users' => [ + 'label' => 'system::lang.permissions.impersonate_users', + 'tab' => 'system::lang.permissions.name', + 'comment' => 'system::lang.permissions.impersonate_users_comment', + 'roles' => [UserRole::CODE_DEVELOPER], + ], + 'backend.manage_preferences' => [ + 'label' => 'system::lang.permissions.manage_preferences', + 'tab' => 'system::lang.permissions.name', + 'roles' => [UserRole::CODE_DEVELOPER, UserRole::CODE_PUBLISHER], + ], + 'backend.manage_editor' => [ + 'label' => 'system::lang.permissions.manage_editor', + 'tab' => 'system::lang.permissions.name', + 'comment' => 'system::lang.permissions.manage_editor_comment', + 'roles' => [UserRole::CODE_DEVELOPER], + ], + 'backend.manage_own_editor' => [ + 'label' => 'system::lang.permissions.manage_own_editor', + 'tab' => 'system::lang.permissions.name', + 'roles' => [UserRole::CODE_DEVELOPER, UserRole::CODE_PUBLISHER], + ], + 'backend.manage_branding' => [ + 'label' => 'system::lang.permissions.manage_branding', + 'tab' => 'system::lang.permissions.name', + 'comment' => 'system::lang.permissions.manage_branding_comment', + 'roles' => [UserRole::CODE_DEVELOPER], + ], + 'media.manage_media' => [ + 'label' => 'backend::lang.permissions.manage_media', + 'tab' => 'system::lang.permissions.name', + 'roles' => [UserRole::CODE_DEVELOPER, UserRole::CODE_PUBLISHER], + ], + 'backend.allow_unsafe_markdown' => [ + 'label' => 'backend::lang.permissions.allow_unsafe_markdown', + 'tab' => 'system::lang.permissions.name', + 'comment' => 'backend::lang.permissions.allow_unsafe_markdown_comment', + 'roles' => [UserRole::CODE_DEVELOPER], + ], + ]); + $manager->registerPermissionOwnerAlias('Winter.Backend', 'October.Backend'); + }); + } + + /** + * Register the backend user events + */ + protected function registerBackendUserEvents() + { + Event::listen('backend.user.login', function (\Backend\Models\User $user) { + // @TODO: Deprecate this, and only run migrations when it makes sense + $runMigrationsOnLogin = (bool) Config::get('cms.runMigrationsOnLogin', Config::get('app.debug', false)); + if ($runMigrationsOnLogin) { + try { + // Load version updates + UpdateManager::instance()->update(); + } catch (Exception $e) { + Flash::error($e->getMessage()); + } + } + + // Log the sign in event + AccessLog::add($user); + }); + } + + /* + * Register widgets + */ + protected function registerBackendWidgets() + { + WidgetManager::instance()->registerFormWidgets(function ($manager) { + $manager->registerFormWidget(\Backend\FormWidgets\CodeEditor::class, 'codeeditor'); + $manager->registerFormWidget(\Backend\FormWidgets\ColorPicker::class, 'colorpicker'); + $manager->registerFormWidget(\Backend\FormWidgets\DataTable::class, 'datatable'); + $manager->registerFormWidget(\Backend\FormWidgets\DatePicker::class, 'datepicker'); + $manager->registerFormWidget(\Backend\FormWidgets\FieldSet::class, 'fieldset'); + $manager->registerFormWidget(\Backend\FormWidgets\FileUpload::class, 'fileupload'); + $manager->registerFormWidget(\Backend\FormWidgets\IconPicker::class, 'iconpicker'); + $manager->registerFormWidget(\Backend\FormWidgets\MarkdownEditor::class, 'markdown'); + $manager->registerFormWidget(\Backend\FormWidgets\MediaFinder::class, 'mediafinder'); + $manager->registerFormWidget(\Backend\FormWidgets\NestedForm::class, 'nestedform'); + $manager->registerFormWidget(\Backend\FormWidgets\RecordFinder::class, 'recordfinder'); + $manager->registerFormWidget(\Backend\FormWidgets\Relation::class, 'relation'); + $manager->registerFormWidget(\Backend\FormWidgets\RelationManager::class, 'relationmanager'); + $manager->registerFormWidget(\Backend\FormWidgets\Repeater::class, 'repeater'); + $manager->registerFormWidget(\Backend\FormWidgets\RichEditor::class, 'richeditor'); + $manager->registerFormWidget(\Backend\FormWidgets\Sensitive::class, 'sensitive'); + $manager->registerFormWidget(\Backend\FormWidgets\TagList::class, 'taglist'); + }); + } + + /* + * Register settings + */ + protected function registerBackendSettings() + { + SettingsManager::instance()->registerCallback(function ($manager) { + $manager->registerSettingItems('Winter.Backend', [ + 'branding' => [ + 'label' => 'backend::lang.branding.menu_label', + 'description' => 'backend::lang.branding.menu_description', + 'category' => SettingsManager::CATEGORY_SYSTEM, + 'icon' => 'icon-paint-brush', + 'class' => 'Backend\Models\BrandSetting', + 'permissions' => ['backend.manage_branding'], + 'order' => 500, + 'keywords' => 'brand style' + ], + 'editor' => [ + 'label' => 'backend::lang.editor.menu_label', + 'description' => 'backend::lang.editor.menu_description', + 'category' => SettingsManager::CATEGORY_SYSTEM, + 'icon' => 'icon-code', + 'class' => 'Backend\Models\EditorSetting', + 'permissions' => ['backend.manage_editor'], + 'order' => 500, + 'keywords' => 'html code class style' + ], + 'myaccount' => [ + 'label' => 'backend::lang.myaccount.menu_label', + 'description' => 'backend::lang.myaccount.menu_description', + 'category' => SettingsManager::CATEGORY_MYSETTINGS, + 'icon' => 'icon-user', + 'url' => Backend::url('backend/myaccount'), + 'order' => 500, + 'context' => 'mysettings', + 'keywords' => 'backend::lang.myaccount.menu_keywords' + ], + 'preferences' => [ + 'label' => 'backend::lang.backend_preferences.menu_label', + 'description' => 'backend::lang.backend_preferences.menu_description', + 'category' => SettingsManager::CATEGORY_MYSETTINGS, + 'icon' => 'icon-laptop', + 'url' => Backend::url('backend/preferences'), + 'permissions' => ['backend.manage_preferences'], + 'order' => 510, + 'context' => 'mysettings' + ], + 'access_logs' => [ + 'label' => 'backend::lang.access_log.menu_label', + 'description' => 'backend::lang.access_log.menu_description', + 'category' => SettingsManager::CATEGORY_LOGS, + 'icon' => 'icon-lock', + 'url' => Backend::url('backend/accesslogs'), + 'permissions' => ['system.access_logs'], + 'order' => 920 + ] + ]); + $manager->registerOwnerAlias('Winter.Backend', 'October.Backend'); + }); + } +} diff --git a/modules/backend/assets/.gitignore b/modules/backend/assets/.gitignore new file mode 100644 index 0000000..5e4176a --- /dev/null +++ b/modules/backend/assets/.gitignore @@ -0,0 +1 @@ +!vendor diff --git a/modules/backend/assets/css/dashboard/dashboard.css b/modules/backend/assets/css/dashboard/dashboard.css new file mode 100644 index 0000000..2fb878c --- /dev/null +++ b/modules/backend/assets/css/dashboard/dashboard.css @@ -0,0 +1,12 @@ +.dashboard-container > .report-container.loading { + position: absolute; + width: 100%; + height: 100%; +} +.dashboard-container > .report-container.loading .loading-indicator-container { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; +} diff --git a/modules/backend/assets/css/winter.css b/modules/backend/assets/css/winter.css new file mode 100644 index 0000000..f550032 --- /dev/null +++ b/modules/backend/assets/css/winter.css @@ -0,0 +1,1118 @@ +@import "../vendor/jcrop/css/jquery.Jcrop.min.css"; +@import "../../../system/assets/vendor/prettify/prettify.css"; +@import "../../../system/assets/vendor/prettify/theme-desert.css"; +@-webkit-keyframes showSweetAlert{0%{transform:scale(0.7);-webkit-transform:scale(0.7)}45%{transform:scale(1.05);-webkit-transform:scale(1.05)}80%{transform:scale(0.95);-webkit-tranform:scale(0.95)}100%{transform:scale(1);-webkit-transform:scale(1)}} +@keyframes showSweetAlert{0%{transform:scale(0.7);-webkit-transform:scale(0.7)}45%{transform:scale(1.05);-webkit-transform:scale(1.05)}80%{transform:scale(0.95);-webkit-tranform:scale(0.95)}100%{transform:scale(1);-webkit-transform:scale(1)}} +@-webkit-keyframes hideSweetAlert{0%{transform:scale(1);-webkit-transform:scale(1)}100%{transform:scale(0.5);-webkit-transform:scale(0.5)}} +@keyframes hideSweetAlert{0%{transform:scale(1);-webkit-transform:scale(1)}100%{transform:scale(0.5);-webkit-transform:scale(0.5)}} +.showSweetAlert{-webkit-animation:showSweetAlert 0.3s;animation:showSweetAlert 0.3s} +.hideSweetAlert{-webkit-animation:hideSweetAlert 0.2s;animation:hideSweetAlert 0.2s} +@-webkit-keyframes animateSuccessTip{0%{width:0;left:1px;top:19px}54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}100%{width:25px;left:14px;top:45px}} +@keyframes animateSuccessTip{0%{width:0;left:1px;top:19px}54%{width:0;left:1px;top:19px}70%{width:50px;left:-8px;top:37px}84%{width:17px;left:21px;top:48px}100%{width:25px;left:14px;top:45px}} +@-webkit-keyframes animateSuccessLong{0%{width:0;right:46px;top:54px}65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}100%{width:47px;right:8px;top:38px}} +@keyframes animateSuccessLong{0%{width:0;right:46px;top:54px}65%{width:0;right:46px;top:54px}84%{width:55px;right:0;top:35px}100%{width:47px;right:8px;top:38px}} +@-webkit-keyframes rotatePlaceholder{0%{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}5%{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}12%{transform:rotate(-405deg);-webkit-transform:rotate(-405deg)}100%{transform:rotate(-405deg);-webkit-transform:rotate(-405deg)}} +@keyframes rotatePlaceholder{0%{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}5%{transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}12%{transform:rotate(-405deg);-webkit-transform:rotate(-405deg)}100%{transform:rotate(-405deg);-webkit-transform:rotate(-405deg)}} +.animateSuccessTip{-webkit-animation:animateSuccessTip 0.75s;animation:animateSuccessTip 0.75s} +.animateSuccessLong{-webkit-animation:animateSuccessLong 0.75s;animation:animateSuccessLong 0.75s} +.icon.success.animate::after{-webkit-animation:rotatePlaceholder 4.25s ease-in;animation:rotatePlaceholder 4.25s ease-in} +@-webkit-keyframes animateErrorIcon{0%{transform:rotateX(100deg);-webkit-transform:rotateX(100deg);opacity:0}100%{transform:rotateX(0deg);-webkit-transform:rotateX(0deg);opacity:1}} +@keyframes animateErrorIcon{0%{transform:rotateX(100deg);-webkit-transform:rotateX(100deg);opacity:0}100%{transform:rotateX(0deg);-webkit-transform:rotateX(0deg);opacity:1}} +.animateErrorIcon{-webkit-animation:animateErrorIcon 0.5s;animation:animateErrorIcon 0.5s} +@-webkit-keyframes animateXMark{0%{transform:scale(0.4);-webkit-transform:scale(0.4);margin-top:26px;opacity:0}50%{transform:scale(0.4);-webkit-transform:scale(0.4);margin-top:26px;opacity:0}80%{transform:scale(1.15);-webkit-transform:scale(1.15);margin-top:-6px}100%{transform:scale(1);-webkit-transform:scale(1);margin-top:0;opacity:1}} +@keyframes animateXMark{0%{transform:scale(0.4);-webkit-transform:scale(0.4);margin-top:26px;opacity:0}50%{transform:scale(0.4);-webkit-transform:scale(0.4);margin-top:26px;opacity:0}80%{transform:scale(1.15);-webkit-transform:scale(1.15);margin-top:-6px}100%{transform:scale(1);-webkit-transform:scale(1);margin-top:0;opacity:1}} +.animateXMark{-webkit-animation:animateXMark 0.5s;animation:animateXMark 0.5s} +@-webkit-keyframes pulseWarning{0%{border-color:#F8D486}100%{border-color:#F8BB86}} +@keyframes pulseWarning{0%{border-color:#F8D486}100%{border-color:#F8BB86}} +.pulseWarning{-webkit-animation:pulseWarning 0.75s infinite alternate;animation:pulseWarning 0.75s infinite alternate} +@-webkit-keyframes pulseWarningIns{0%{background-color:#F8D486}100%{background-color:#F8BB86}} +@keyframes pulseWarningIns{0%{background-color:#F8D486}100%{background-color:#F8BB86}} +.pulseWarningIns{-webkit-animation:pulseWarningIns 0.75s infinite alternate;animation:pulseWarningIns 0.75s infinite alternate} +.sweet-overlay{background-color:rgba(0,0,0,0.4);position:fixed;left:0;right:0;top:0;bottom:0;display:none;z-index:7600} +.sweet-alert{background-color:#f9f9f9;width:478px;padding:17px;border-radius:5px;text-align:center;position:fixed;left:50%;top:50%;margin-left:-256px;margin-top:-200px;overflow:hidden;display:none;z-index:8600} +@media all and (max-width:767px){.sweet-alert{width:auto;margin-left:0;margin-right:0;left:15px;right:15px}} +.sweet-alert .icon{width:80px;height:80px;border:4px solid gray;border-radius:50%;margin:20px auto;position:relative;box-sizing:content-box} +.sweet-alert .icon.error{border-color:#c8113f} +.sweet-alert .icon.error .x-mark{position:relative;display:block} +.sweet-alert .icon.error .line{position:absolute;height:5px;width:47px;background-color:#e01346;display:block;top:37px;border-radius:2px} +.sweet-alert .icon.error .line.left{-webkit-transform:rotate(45deg);transform:rotate(45deg);left:17px} +.sweet-alert .icon.error .line.right{-webkit-transform:rotate(-45deg);transform:rotate(-45deg);right:16px} +.sweet-alert .icon.warning{border-color:#da783f} +.sweet-alert .icon.warning .body{position:absolute;width:5px;height:47px;left:50%;top:10px;border-radius:2px;margin-left:-2px;background-color:#de8754} +.sweet-alert .icon.warning .dot{position:absolute;width:7px;height:7px;border-radius:50%;margin-left:-3px;left:50%;bottom:10px;background-color:#de8754} +.sweet-alert .icon.info{border-color:#33b1d0} +.sweet-alert .icon.info::before{content:"";position:absolute;width:5px;height:29px;left:50%;bottom:17px;border-radius:2px;margin-left:-2px;background-color:#48b9d5} +.sweet-alert .icon.info::after{content:"";position:absolute;width:7px;height:7px;border-radius:50%;margin-left:-3px;top:19px;background-color:#48b9d5} +.sweet-alert .icon.success{border-color:#499532} +.sweet-alert .icon.success::before, +.sweet-alert .icon.success::after{content:'';border-radius:50%;position:absolute;width:60px;height:120px;background:white;-webkit-transform:rotate(45deg);transform:rotate(45deg)} +.sweet-alert .icon.success::before{border-radius:120px 0 0 120px;top:-7px;left:-33px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:60px 60px;transform-origin:60px 60px} +.sweet-alert .icon.success::after{border-radius:0 120px 120px 0;top:-11px;left:30px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);-webkit-transform-origin:0 60px;transform-origin:0 60px} +.sweet-alert .icon.success .placeholder{width:80px;height:80px;border:4px solid rgba(82,168,56,0.2);border-radius:50%;box-sizing:content-box;position:absolute;left:-4px;top:-4px;z-index:2} +.sweet-alert .icon.success .fix{width:5px;height:90px;background-color:#f9f9f9;position:absolute;left:28px;top:8px;z-index:1;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)} +.sweet-alert .icon.success .line{height:5px;background-color:#52a838;display:block;border-radius:2px;position:absolute;z-index:2} +.sweet-alert .icon.success .line.tip{width:25px;left:14px;top:46px;-webkit-transform:rotate(45deg);transform:rotate(45deg)} +.sweet-alert .icon.success .line.long{width:47px;right:8px;top:38px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)} +.sweet-alert .icon.custom{background-size:contain;border-radius:0;border:none;background-position:center center;background-repeat:no-repeat} +.sweet-alert .btn-default:focus{border-color:#656d79;outline:0} +.sweet-alert .btn-success:focus{border-color:#499532;outline:0} +.sweet-alert .btn-info:focus{border-color:#33b1d0;outline:0} +.sweet-alert .btn-danger:focus{border-color:#c8113f;outline:0} +.sweet-alert .btn-warning:focus{border-color:#da783f;outline:0} +.sweet-alert button::-moz-focus-inner{border:0} +.sweet-overlay{background-color:rgba(0,0,0,0.2);z-index:10499} +.sweet-alert{text-align:right;border-radius:3px;-webkit-box-shadow:0 27px 24px 0 rgba(0,0,0,0.2),0 40px 77px 0 rgba(0,0,0,0.22);box-shadow:0 27px 24px 0 rgba(0,0,0,0.2),0 40px 77px 0 rgba(0,0,0,0.22);z-index:10500} +.sweet-alert h2{word-break:break-word;word-wrap:break-word;max-height:350px;overflow-y:auto;margin:10px 0 17px 0;color:#2b3e50;text-align:left;font-size:15px;line-height:23px} +.sweet-alert p{margin:0} +.sweet-alert p.text-muted{margin-bottom:20px;color:#555} +.global-notice{position:sticky;top:0;display:flex;align-items:center;flex-wrap:wrap;gap:0.5em;justify-content:space-between;z-index:10500;background:#ab2a1c;color:#FFF;padding:0.5em 0.75em} +.global-notice .notice-icon{font-size:1.5em;vertical-align:bottom;display:inline-block;margin-right:0.25em} +.global-notice .notice-text{display:inline-block;vertical-align:middle} +.control-simplelist{font-size:13px;padding:20px 20px 2px 20px;margin-bottom:20px;background:#FFF;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} +.control-simplelist ul{padding-left:15px} +.control-simplelist.form-control ul{margin-bottom:0} +.control-simplelist.form-control li{padding-top:5px;padding-bottom:5px} +.control-simplelist.with-icons ul, +.control-simplelist.with-checkboxes ul, +.control-simplelist.is-divided ul, +.control-simplelist.is-selectable ul{list-style-type:none;padding-left:0} +.control-simplelist.with-checkboxes li{margin-top:-5px} +.control-simplelist.with-checkboxes li:first-child{margin-top:0} +.control-simplelist.with-checkboxes li:last-child div.custom-checkbox{margin-bottom:0} +.control-simplelist.with-checkboxes li:last-child div.custom-checkbox label{margin-bottom:5px} +.control-simplelist.is-sortable li.placeholder{position:relative} +.control-simplelist.is-sortable li.placeholder:before{top:-10px;position:absolute;content:'';display:block;width:0;height:0;border-top:4.5px solid transparent;border-bottom:4.5px solid transparent;border-left:5px solid #999} +.control-simplelist.is-sortable li.dragged{position:absolute;opacity:0.5;filter:alpha(opacity=50);z-index:2000;color:#2da7c7;width:auto !important} +.control-simplelist.is-scrollable{height:200px} +.control-simplelist.is-scrollable.size-tiny{min-height:250px} +.control-simplelist.is-scrollable.size-small{min-height:300px} +.control-simplelist.is-scrollable.size-large{min-height:400px} +.control-simplelist.is-scrollable.size-huge{min-height:450px} +.control-simplelist.is-scrollable.size-giant{min-height:550px} +.control-simplelist.is-divided, +.control-simplelist.is-selectable, +.control-simplelist.is-selectable-box{padding:0} +.control-simplelist.is-divided li .heading, +.control-simplelist.is-selectable li .heading, +.control-simplelist.is-selectable-box li .heading{font-size:14px;font-weight:500} +.control-simplelist.is-divided li, +.control-simplelist.is-selectable li{padding:5px 10px;border-bottom:1px solid #D4D8DA} +.control-simplelist.is-divided li:last-child, +.control-simplelist.is-selectable li:last-child{border-bottom:none} +.control-simplelist.is-selectable li a{padding:5px 10px;margin:-5px -10px;display:block;color:#333} +.control-simplelist.is-selectable li:hover{background:#48b2ce;cursor:pointer} +.control-simplelist.is-selectable li:hover, +.control-simplelist.is-selectable li:hover a{color:white} +.control-simplelist.is-selectable li:hover a{text-decoration:none} +.control-simplelist.is-selectable li.active a{background:#f0f0f0} +.control-simplelist.is-selectable li.active a:hover{background:#48b2ce} +.control-simplelist.is-selectable-box{padding-top:15px;margin-bottom:0} +.control-simplelist.is-selectable-box li{width:155px;margin:8px;display:inline-block;text-align:center;vertical-align:top} +.control-simplelist.is-selectable-box li a{text-decoration:none;display:block;color:#333} +.control-simplelist.is-selectable-box li a .box{display:block;width:155px;height:155px;border:3px solid rgba(0,0,0,0.1);position:relative;-webkit-transition:border 0.3s ease;transition:border 0.3s ease} +.control-simplelist.is-selectable-box li a .image{display:block;width:56px;height:56px;position:absolute;top:50%;left:50%;margin-top:-28px;margin-left:-28px} +.control-simplelist.is-selectable-box li a .image>i{font-size:56px;color:rgba(0,0,0,0.25)} +.control-simplelist.is-selectable-box li a .heading{margin:7px 0;padding:0} +.control-simplelist.is-selectable-box li a .description{font-size:12px} +.control-simplelist.is-selectable-box li a:hover .box{border-color:rgba(0,0,0,0.2)} +.control-simplelist.is-selectable-box li a:hover .image>i{color:rgba(0,0,0,0.45)} +.list-preview .control-simplelist.is-selectable ul{margin-bottom:0} +.drag-noselect{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} +.control-scrollbar{position:relative;overflow:hidden;height:100%} +.control-scrollbar>.scrollbar-scrollbar{position:absolute;z-index:100} +.control-scrollbar>.scrollbar-scrollbar .scrollbar-track{background-color:transparent;position:relative;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px} +.control-scrollbar>.scrollbar-scrollbar .scrollbar-track .scrollbar-thumb{background-color:rgba(0,0,0,0.35);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;cursor:pointer;overflow:hidden;position:absolute} +.control-scrollbar>.scrollbar-scrollbar.disabled{display:none !important} +.control-scrollbar.vertical>.scrollbar-scrollbar{right:0;margin-right:5px;width:6px} +.control-scrollbar.vertical>.scrollbar-scrollbar .scrollbar-track{height:100%;width:6px} +.control-scrollbar.vertical>.scrollbar-scrollbar .scrollbar-track .scrollbar-thumb{height:20px;width:6px;top:0;left:0} +.control-scrollbar.vertical>.scrollbar-scrollbar:active, +.control-scrollbar.vertical>.scrollbar-scrollbar:hover{width:8px;-webkit-transition:width 0.3s;transition:width 0.3s} +.control-scrollbar.vertical>.scrollbar-scrollbar:active .scrollbar-track, +.control-scrollbar.vertical>.scrollbar-scrollbar:hover .scrollbar-track, +.control-scrollbar.vertical>.scrollbar-scrollbar:active .scrollbar-thumb, +.control-scrollbar.vertical>.scrollbar-scrollbar:hover .scrollbar-thumb{width:8px;-webkit-transition:width 0.3s;transition:width 0.3s} +.control-scrollbar.horizontal>.scrollbar-scrollbar{margin:0 0 5px;clear:both;height:6px} +.control-scrollbar.horizontal>.scrollbar-scrollbar .scrollbar-track{width:100%;height:6px} +.control-scrollbar.horizontal>.scrollbar-scrollbar .scrollbar-track .scrollbar-thumb{height:6px;margin:2px 0;left:0;top:0} +.control-scrollbar.horizontal>.scrollbar-scrollbar:active, +.control-scrollbar.horizontal>.scrollbar-scrollbar:hover{height:8px;-webkit-transition:height 0.3s;transition:height 0.3s} +.control-scrollbar.horizontal>.scrollbar-scrollbar:active .scrollbar-track, +.control-scrollbar.horizontal>.scrollbar-scrollbar:hover .scrollbar-track, +.control-scrollbar.horizontal>.scrollbar-scrollbar:active .scrollbar-thumb, +.control-scrollbar.horizontal>.scrollbar-scrollbar:hover .scrollbar-thumb{height:8px;-webkit-transition:height 0.3s;transition:height 0.3s} +html.mobile .control-scrollbar{overflow:auto;-webkit-overflow-scrolling:touch} +.no-touch .control-scrollbar>.scrollbar-scrollbar{opacity:0;-webkit-transition:opacity 0.3s;transition:opacity 0.3s} +.no-touch .control-scrollbar:active>.scrollbar-scrollbar, +.no-touch .control-scrollbar:hover>.scrollbar-scrollbar{opacity:1} +@media (max-width:768px){.responsive-sidebar>.layout-cell:last-child .control-scrollbar{overflow:visible;height:auto}.responsive-sidebar>.layout-cell:last-child .control-scrollbar .scrollbar-scrollbar{display:none!important}} +.control-filelist p.no-data{padding:22px 0;margin:0;color:#666;font-size:14px;text-align:center;font-weight:normal;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} +.control-filelist ul{padding:0;margin:0} +.control-filelist ul li{font-weight:normal;line-height:150%;position:relative;list-style:none} +.control-filelist ul li a:hover{background:#ddd} +.control-filelist ul li.active>a{background:#ddd;position:relative} +.control-filelist ul li.active>a:after{position:absolute;height:100%;width:4px;left:0;top:0;background:#2da7c7;display:block;content:' '} +.control-filelist ul li a{display:block;padding:10px 45px 10px 20px;outline:none} +.control-filelist ul li a:hover, +.control-filelist ul li a:focus, +.control-filelist ul li a:active{text-decoration:none} +.control-filelist ul li a span{display:block} +.control-filelist ul li a span.title{font-weight:normal;color:#405261;font-size:14px} +.control-filelist ul li a span.description{color:#8f8f8f;font-size:12px;white-space:nowrap;font-weight:normal;overflow:hidden;text-overflow:ellipsis} +.control-filelist ul li a span.description strong{color:#405261;font-weight:normal} +.control-filelist ul li.group>h4, +.control-filelist ul li.group>div.group>h4{font-weight:normal;font-size:14px;margin-top:0;margin-bottom:0;position:relative} +.control-filelist ul li.group>h4 a, +.control-filelist ul li.group>div.group>h4 a{padding:10px 20px 10px 53px;color:#405261;position:relative;outline:none} +.control-filelist ul li.group>h4 a:hover, +.control-filelist ul li.group>div.group>h4 a:hover{background:transparent} +.control-filelist ul li.group>h4 a:before, +.control-filelist ul li.group>div.group>h4 a:before, +.control-filelist ul li.group>h4 a:after, +.control-filelist ul li.group>div.group>h4 a:after{width:10px;height:10px;display:block;position:absolute;top:1px} +.control-filelist ul li.group>h4 a:after, +.control-filelist ul li.group>div.group>h4 a:after{left:33px;top:9px;font-family:"Font Awesome 6 Free";font-weight:900;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-style:normal;font-variant:normal;text-rendering:auto;content:"\f07b";color:#a1aab1;font-size:16px} +.control-filelist ul li.group>h4 a:before, +.control-filelist ul li.group>div.group>h4 a:before{left:20px;top:9px;color:#cfcfcf;font-family:"Font Awesome 6 Free";font-weight:900;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-style:normal;font-variant:normal;text-rendering:auto;content:"\f0da";-webkit-transform:rotate(90deg) translate(5px,0);-ms-transform:rotate(90deg) translate(5px,0);transform:rotate(90deg) translate(5px,0);-webkit-transition:all 0.1s ease;transition:all 0.1s ease} +.control-filelist ul li.group>ul>li>a{padding-left:52px} +.control-filelist ul li.group>ul>li.group{padding-left:20px} +.control-filelist ul li.group>ul>li.group>ul>li>a{padding-left:324px;margin-left:-270px} +.control-filelist ul li.group>ul>li.group>ul>li.group>ul>li>a{padding-left:297px;margin-left:-243px} +.control-filelist ul li.group>ul>li.group>ul>li.group>ul>li.group>ul>li>a{padding-left:270px;margin-left:-216px} +.control-filelist ul li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li>a{padding-left:243px;margin-left:-189px} +.control-filelist ul li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li>a{padding-left:216px;margin-left:-162px} +.control-filelist ul li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li>a{padding-left:189px;margin-left:-135px} +.control-filelist ul li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li>a{padding-left:162px;margin-left:-108px} +.control-filelist ul li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li>a{padding-left:135px;margin-left:-81px} +.control-filelist ul li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li>a{padding-left:108px;margin-left:-54px} +.control-filelist ul li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li.group>ul>li>a{padding-left:81px;margin-left:-27px} +.control-filelist ul li.group[data-status=collapsed]>h4 a:before, +.control-filelist ul li.group[data-status=collapsed]>div.group>h4 a:before{-webkit-transform:rotate(0deg) translate(3px,0);-ms-transform:rotate(0deg) translate(3px,0);transform:rotate(0deg) translate(3px,0)} +.control-filelist ul li.group[data-status=collapsed]>ul, +.control-filelist ul li.group[data-status=collapsed]>div.subitems{display:none} +.control-filelist ul li>div.controls{position:absolute;right:19px;top:6px} +.control-filelist ul li>div.controls .dropdown{width:14px;height:21px} +.control-filelist ul li>div.controls .dropdown.open a.control{display:block!important} +.control-filelist ul li>div.controls .dropdown.open a.control:before{visibility:visible;display:block} +.control-filelist ul li>div.controls a.control{color:#405261;font-size:14px;visibility:hidden;overflow:hidden;width:14px;height:21px;display:none;text-decoration:none;cursor:pointer;padding:0;opacity:0.5;filter:alpha(opacity=50)} +.control-filelist ul li>div.controls a.control:before{visibility:visible;display:block;margin-right:0} +.control-filelist ul li>div.controls a.control:hover{opacity:1;filter:alpha(opacity=100)} +.control-filelist ul li:hover>div.controls, +.control-filelist ul li:hover>a.control{display:block!important} +.control-filelist ul li:hover>div.controls>a.control, +.control-filelist ul li:hover>a.control>a.control{display:block!important} +.control-filelist ul li .checkbox{position:absolute;top:-5px;right:0} +.control-filelist ul li .checkbox label{margin-right:0} +.control-filelist ul li .checkbox label:before{border-color:#ccc} +.control-filelist.single-line ul li a span.title{text-overflow:ellipsis;overflow:hidden;white-space:nowrap} +.control-filelist.filelist-hero ul li{background:#fff;border-bottom:none} +.control-filelist.filelist-hero ul li>a{padding:11px 45px 10px 50px;font-size:13px;border-bottom:1px solid #ECF0F1} +.control-filelist.filelist-hero ul li>a span.title{font-size:14px;font-weight:normal;color:#2b3e50} +.control-filelist.filelist-hero ul li>a span.description{font-size:13px} +.control-filelist.filelist-hero ul li>a .list-icon{position:absolute;left:14px;top:50%;transform:translateY(-50%);font-size:22px;color:#b7c0c2} +.control-filelist.filelist-hero ul li>a:hover{background:#48b2ce;border-bottom:1px solid #48b2ce !important} +.control-filelist.filelist-hero ul li>a:hover span.title, +.control-filelist.filelist-hero ul li>a:hover span.description{color:#fff !important} +.control-filelist.filelist-hero ul li>a:hover .list-icon{color:#fff !important} +.control-filelist.filelist-hero ul li>a:active{background:#6cc551;border-bottom:1px solid #6cc551 !important} +.control-filelist.filelist-hero ul li>a:active span.title, +.control-filelist.filelist-hero ul li>a:active span.description{color:#fff !important} +.control-filelist.filelist-hero ul li>a:active .list-icon{color:#fff !important} +.control-filelist.filelist-hero ul li .checkbox{top:-2px;right:0} +.control-filelist.filelist-hero ul li.active>a{border-bottom:1px solid #ddd} +.control-filelist.filelist-hero ul li.active>a:after{top:-1px;bottom:-1px;height:auto} +.control-filelist.filelist-hero ul li.active>a>span.borders:before{content:' ';position:absolute;width:100%;height:1px;display:block;left:0;background-color:#ddd} +.control-filelist.filelist-hero ul li.active>a>span.borders:before{top:-1px} +.control-filelist.filelist-hero ul li.active>a:hover>span.borders:before{background-color:#48b2ce} +.control-filelist.filelist-hero ul li.active>a:active>span.borders:before{background-color:#6cc551} +.control-filelist.filelist-hero ul li>h4{padding-top:7px;padding-bottom:6px;border-bottom:1px solid #ECF0F1} +.control-filelist.filelist-hero ul li>div.controls{display:none;position:absolute;right:16px;top:15px} +.control-filelist.filelist-hero ul li>div.controls>a.control{width:16px;height:23px;background:transparent;overflow:hidden;display:inline-block;color:#fff !important;padding:0} +.control-filelist.filelist-hero ul li>div.controls>a.control:before{font-size:17px} +.control-filelist.filelist-hero ul li:hover>div.controls{display:block} +.control-filelist.filelist-hero ul li.separator{position:relative;border-bottom:1px solid #95a5a6;padding:12px 15px 13px 15px} +.control-filelist.filelist-hero ul li.separator:before{z-index:31;content:'';display:block;width:0;height:0;border-left:9.5px solid transparent;border-right:9.5px solid transparent;border-top:11px solid white;border-bottom-width:0;position:absolute;left:13px;bottom:-8px} +.control-filelist.filelist-hero ul li.separator:after{z-index:30;content:'';display:block;width:0;height:0;border-left:8.5px solid transparent;border-right:8.5px solid transparent;border-top:9px solid #95a5a6;border-bottom-width:0;position:absolute;left:14px;bottom:-9px} +.control-filelist.filelist-hero ul li.separator h5{color:#2b3e50;font-size:14px;margin:0;font-weight:normal;padding:0} +.control-filelist.filelist-hero ul>li.group>ul>li>a{padding-left:66px} +.control-filelist.filelist-hero.single-level ul li:hover{background:#48b2ce} +.control-filelist.filelist-hero.single-level ul li:hover>a{background:#48b2ce;border-bottom:1px solid #48b2ce !important} +.control-filelist.filelist-hero.single-level ul li:hover>a span.title, +.control-filelist.filelist-hero.single-level ul li:hover>a span.description{color:#fff !important} +.control-filelist.filelist-hero.single-level ul li:hover>a .list-icon{color:#fff !important} +.control-filelist.filelist-hero.single-level ul li:active{background:#6cc551} +.control-filelist.filelist-hero.single-level ul li:active>a{background:#6cc551;border-bottom:1px solid #6cc551 !important} +.control-filelist.filelist-hero.single-level ul li:active>a span.title, +.control-filelist.filelist-hero.single-level ul li:active>a span.description{color:#fff !important} +.control-filelist.filelist-hero.single-level ul li:active>a .list-icon{color:#fff !important} +.control-scrollpanel{position:relative;background:#ECF0F1} +.control-scrollpanel .control-scrollbar.vertical>.scrollbar-scrollbar{right:0} +.tooltip .tooltip-inner{text-align:left;padding:5px 8px} +.tooltip.in{opacity:1;filter:alpha(opacity=100)} +.wn-logo-white, +.oc-logo-white{background-image:url(../images/winter-logo-white.svg);background-position:50% 50%;background-repeat:no-repeat;background-size:contain} +.wn-logo, +.oc-logo{background-image:url(../images/winter-logo.svg);background-position:50% 50%;background-repeat:no-repeat;background-size:contain} +.layout.control-tabs.wn-logo-transparent:not(.has-tabs), +.layout.control-tabs.oc-logo-transparent:not(.has-tabs), +.flex-layout-column.wn-logo-transparent:not(.has-tabs), +.flex-layout-column.oc-logo-transparent:not(.has-tabs), +.layout-cell.wn-logo-transparent, +.layout-cell.oc-logo-transparent{background-size:50% auto;background-repeat:no-repeat;background-image:url(../images/winter-logo.svg);background-position:50% 50%;position:relative} +.layout.control-tabs.wn-logo-transparent:not(.has-tabs):after, +.layout.control-tabs.oc-logo-transparent:not(.has-tabs):after, +.flex-layout-column.wn-logo-transparent:not(.has-tabs):after, +.flex-layout-column.oc-logo-transparent:not(.has-tabs):after, +.layout-cell.wn-logo-transparent:after, +.layout-cell.oc-logo-transparent:after{content:'';display:table-cell;position:absolute;left:0;top:0;height:100%;width:100%;background:rgba(249,249,249,0.7)} +.report-widget{padding:15px;background:white;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;font-size:13px} +.report-widget h3{font-size:14px;color:#7e8c8d;text-transform:uppercase;font-weight:600;margin-top:0;margin-bottom:30px} +.report-widget .height-100{height:100px} +.report-widget .height-200{height:200px} +.report-widget .height-300{height:300px} +.report-widget .height-400{height:400px} +.report-widget .height-500{height:500px} +.report-widget p.report-description{margin-bottom:0;margin-top:15px;font-size:12px;line-height:190%;color:#7e8c8d} +.report-widget a:not(.btn){color:#7e8c8d;text-decoration:none} +.report-widget a:not(.btn):hover{color:#2da7c7;text-decoration:none} +.report-widget p.flash-message.static{margin-bottom:0} +.report-widget .icon-circle.success{color:#52a838} +.report-widget .icon-circle.primary{color:#103141} +.report-widget .icon-circle.warning{color:#de8754} +.report-widget .icon-circle.danger{color:#e01346} +.report-widget .icon-circle.info{color:#48b9d5} +.control-treelist ol{padding:0;margin:0;list-style:none} +.control-treelist ol ol{margin:0;margin-left:15px;padding-left:15px;border-left:1px solid #dbdee0} +.control-treelist>ol>li>div.record:before{display:none} +.control-treelist li{margin:0;padding:0} +.control-treelist li>div.record{margin:0;font-size:12px;margin-bottom:5px;position:relative;display:block} +.control-treelist li>div.record:before{color:#bdc3c7;font-family:"Font Awesome 6 Free";font-weight:900;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-style:normal;font-variant:normal;text-rendering:auto;content:"\f111";font-size:6px;position:absolute;left:-18px;top:11px} +.control-treelist li>div.record>a.move{display:inline-block;padding:7px 0 7px 10px;text-decoration:none;color:#bdc3c7} +.control-treelist li>div.record>a.move:hover{color:#48b2ce} +.control-treelist li>div.record>a.move:before{font-family:"Font Awesome 6 Free";font-weight:900;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-style:normal;font-variant:normal;text-rendering:auto;content:"\f0c9"} +.control-treelist li>div.record>span{color:#666;display:inline-block;padding:7px 15px 7px 5px} +.control-treelist li.dragged{position:absolute;z-index:2000;width:auto !important;height:auto !important} +.control-treelist li.dragged>div.record{opacity:0.5;filter:alpha(opacity=50);background:#48b2ce !important} +.control-treelist li.dragged>div.record>a.move:before, +.control-treelist li.dragged>div.record>span{color:white} +.control-treelist li.dragged>div.record:before{display:none} +.control-treelist li.placeholder{display:inline-block;position:relative;background:#48b2ce !important;height:25px;margin-bottom:5px} +.control-treelist li.placeholder:before{display:block;position:absolute;font-family:"Font Awesome 6 Free";font-weight:900;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-style:normal;font-variant:normal;text-rendering:auto;content:"\f053";color:#d35714;left:-10px;top:8px;z-index:2000} +.control-treeview{margin-bottom:40px} +.control-treeview ol{margin:0;padding:0;list-style:none;background:#fff} +.control-treeview ol>li{-webkit-transition:width 1s;transition:width 1s} +.control-treeview ol>li>div{font-size:14px;font-weight:normal;background:#fff;border-bottom:1px solid #ECF0F1;position:relative} +.control-treeview ol>li>div>a{color:#2b3e50;padding:11px 45px 10px 61px;display:block;line-height:150%;text-decoration:none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} +.control-treeview ol>li>div:before{content:' ';background-image:url(../images/treeview-icons.png);background-position:0 -28px;background-repeat:no-repeat;background-size:42px auto;position:absolute;width:21px;height:22px;left:28px;top:15px} +.control-treeview ol>li>div span.comment{display:block;font-weight:400;color:#95a5a6;font-size:13px;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} +.control-treeview ol>li>div>span.expand{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;display:none;position:absolute;width:20px;height:20px;top:19px;left:2px;cursor:pointer;color:#bdc3c7;-webkit-transition:transform 0.1s ease;transition:transform 0.1s ease} +.control-treeview ol>li>div>span.expand:before{font-family:"Font Awesome 6 Free";font-weight:900;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-style:normal;font-variant:normal;text-rendering:auto;content:"\f0da";line-height:100%;font-size:15px;position:relative;left:8px;top:2px} +.control-treeview ol>li>div>span.drag-handle{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;-webkit-transition:opacity 0.4s;transition:opacity 0.4s;position:absolute;right:9px;bottom:0;width:18px;height:19px;cursor:move;color:#bdc3c7;opacity:0;filter:alpha(opacity=0)} +.control-treeview ol>li>div>span.drag-handle:before{font-family:"Font Awesome 6 Free";font-weight:900;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-style:normal;font-variant:normal;text-rendering:auto;content:"\f0c9";font-size:18px} +.control-treeview ol>li>div span.borders{font-size:0} +.control-treeview ol>li>div>ul.submenu{position:absolute;left:20px;bottom:-36.9px;padding:0;list-style:none;z-index:200;height:37px;display:none;margin-left:15px;background:transparent url(../images/treeview-submenu-tabs.png) repeat-x left -39px} +.control-treeview ol>li>div>ul.submenu:before, +.control-treeview ol>li>div>ul.submenu:after{background:transparent url(../images/treeview-submenu-tabs.png) no-repeat left top;content:' ';display:block;width:20px;height:37px;position:absolute;top:0} +.control-treeview ol>li>div>ul.submenu:before{left:-20px} +.control-treeview ol>li>div>ul.submenu:after{background-position:-100px top;right:-20px} +.control-treeview ol>li>div>ul.submenu li{font-size:12px} +.control-treeview ol>li>div>ul.submenu li a{display:block;padding:4px 3px 0 3px;color:#fff;text-decoration:none;outline:none} +.control-treeview ol>li>div>ul.submenu li a i{margin-right:5px} +.control-treeview ol>li>div:hover>ul.submenu{display:block} +.control-treeview ol>li>div:active>ul.submenu{background-position:left -116px} +.control-treeview ol>li>div:active>ul.submenu:before{background-position:left -77px} +.control-treeview ol>li>div:active>ul.submenu:after{background-position:-100px -77px} +.control-treeview ol>li>div .checkbox{position:absolute;top:-2px;right:0} +.control-treeview ol>li>div .checkbox label{margin-right:0} +.control-treeview ol>li>div .checkbox label:before{border-color:#ccc} +.control-treeview ol>li>div.popover-highlight{background-color:#48b2ce !important} +.control-treeview ol>li>div.popover-highlight:before{background-position:0 -80px} +.control-treeview ol>li>div.popover-highlight>a{color:#fff !important;cursor:default} +.control-treeview ol>li>div.popover-highlight span{color:#fff !important} +.control-treeview ol>li>div.popover-highlight>ul.submenu, +.control-treeview ol>li>div.popover-highlight>span.drag-handle{display:none!important} +.control-treeview ol>li.dragged div, +.control-treeview ol>li>div:hover{background-color:#48b2ce !important} +.control-treeview ol>li.dragged div>a, +.control-treeview ol>li>div:hover>a{color:#fff !important} +.control-treeview ol>li.dragged div:before, +.control-treeview ol>li>div:hover:before{background-position:0 -80px} +.control-treeview ol>li.dragged div:after, +.control-treeview ol>li>div:hover:after{top:0 !important;bottom:0 !important} +.control-treeview ol>li.dragged div span, +.control-treeview ol>li>div:hover span{color:#fff !important} +.control-treeview ol>li.dragged div span.drag-handle, +.control-treeview ol>li>div:hover span.drag-handle{cursor:move;opacity:1;filter:alpha(opacity=100)} +.control-treeview ol>li.dragged div span.borders, +.control-treeview ol>li>div:hover span.borders{display:none} +.control-treeview ol>li>div:active{background-color:#6cc551 !important} +.control-treeview ol>li>div:active>a{color:#fff !important} +.control-treeview ol>li[data-no-drag-mode] div:hover span.drag-handle{cursor:default!important;opacity:0.3 !important;filter:alpha(opacity=30) !important} +.control-treeview ol>li.dragged li.has-subitems>div:before, +.control-treeview ol>li.dragged.has-subitems>div:before{background-position:0 -52px} +.control-treeview ol>li.dragged div>ul.submenu{display:none!important} +.control-treeview ol>li>ol{padding-left:20px;padding-right:20px} +.control-treeview ol>li[data-status=collapsed]>ol{display:none} +.control-treeview ol>li.has-subitems>div:before{background-position:0 0;width:23px;height:26px;left:26px} +.control-treeview ol>li.has-subitems>div:hover:before, +.control-treeview ol>li.has-subitems>div.popover-highlight:before{background-position:0 -52px} +.control-treeview ol>li.has-subitems>div span.expand{display:block} +.control-treeview ol>li.placeholder{position:relative;opacity:0.5;filter:alpha(opacity=50)} +.control-treeview ol>li.placeholder ol{display:none} +.control-treeview ol>li.dragged{position:absolute;z-index:2000;opacity:0.25;filter:alpha(opacity=25)} +.control-treeview ol>li.dragged>div{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px} +.control-treeview ol>li.dragged ol{display:none} +.control-treeview ol>li.drop-target>div{background-color:#2581b8 !important} +.control-treeview ol>li.drop-target>div>a{color:#fff} +.control-treeview ol>li.drop-target>div>a>span.comment{color:#fff} +.control-treeview ol>li.drop-target>div:before{background-position:0 -80px} +.control-treeview ol>li.drop-target.has-subitems>div:before{background-position:0 -52px} +.control-treeview ol>li[data-status=expanded]>div>span.expand{-webkit-transform:rotate(90deg) translate(0,0);-ms-transform:rotate(90deg) translate(0,0);transform:rotate(90deg) translate(0,0)} +.control-treeview ol>li.drag-ghost{background-color:transparent;box-sizing:content-box} +.control-treeview ol>li.active>div{background:#ddd} +.control-treeview ol>li.active>div:after{position:absolute;width:4px;left:0;top:-1px;bottom:-1px;background:#2da7c7;display:block;content:' '} +.control-treeview ol>li.active>div>span.comment, +.control-treeview ol>li.active>div>span.expand{color:#8f8f8f} +.control-treeview ol>li.active>div>span.borders:before, +.control-treeview ol>li.active>div>span.borders:after{content:' ';position:absolute;width:100%;height:1px;display:block;left:0;background-color:#ddd} +.control-treeview ol>li.active>div>span.borders:before{top:-1px} +.control-treeview ol>li.active>div>span.borders:after{bottom:-1px} +.control-treeview ol>li.no-data{padding:18px 0;margin:0;color:#666;font-size:14px;text-align:center;font-weight:400} +.control-treeview ol>li>ol>li>div{margin-left:-20px;margin-right:-20px;padding-left:71px} +.control-treeview ol>li>ol>li>div>a{margin-left:-71px;padding-left:71px} +.control-treeview ol>li>ol>li>div:before{margin-left:10px} +.control-treeview ol>li>ol>li>div>span.expand{left:12px} +.control-treeview ol>li>ol>li>ol>li>div{margin-left:-40px;margin-right:-40px;padding-left:81px} +.control-treeview ol>li>ol>li>ol>li>div>a{margin-left:-81px;padding-left:81px} +.control-treeview ol>li>ol>li>ol>li>div:before{margin-left:20px} +.control-treeview ol>li>ol>li>ol>li>div>span.expand{left:22px} +.control-treeview ol>li>ol>li>ol>li>ol>li>div{margin-left:-60px;margin-right:-60px;padding-left:91px} +.control-treeview ol>li>ol>li>ol>li>ol>li>div>a{margin-left:-91px;padding-left:91px} +.control-treeview ol>li>ol>li>ol>li>ol>li>div:before{margin-left:30px} +.control-treeview ol>li>ol>li>ol>li>ol>li>div>span.expand{left:32px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>div{margin-left:-80px;margin-right:-80px;padding-left:101px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>div>a{margin-left:-101px;padding-left:101px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>div:before{margin-left:40px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>div>span.expand{left:42px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div{margin-left:-100px;margin-right:-100px;padding-left:111px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div>a{margin-left:-111px;padding-left:111px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div:before{margin-left:50px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div>span.expand{left:52px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div{margin-left:-120px;margin-right:-120px;padding-left:121px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div>a{margin-left:-121px;padding-left:121px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div:before{margin-left:60px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div>span.expand{left:62px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div{margin-left:-140px;margin-right:-140px;padding-left:131px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div>a{margin-left:-131px;padding-left:131px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div:before{margin-left:70px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div>span.expand{left:72px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div{margin-left:-160px;margin-right:-160px;padding-left:141px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div>a{margin-left:-141px;padding-left:141px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div:before{margin-left:80px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div>span.expand{left:82px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div{margin-left:-180px;margin-right:-180px;padding-left:151px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div>a{margin-left:-151px;padding-left:151px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div:before{margin-left:90px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div>span.expand{left:92px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div{margin-left:-200px;margin-right:-200px;padding-left:161px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div>a{margin-left:-161px;padding-left:161px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div:before{margin-left:100px} +.control-treeview ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>ol>li>div>span.expand{left:102px} +.control-treeview p.no-data{padding:18px 0;margin:0;color:#666;font-size:14px;text-align:center;font-weight:400} +.control-treeview a.menu-control{display:block;margin:20px;padding:13px 15px;border:dotted 2px #ebebeb;color:#bdc3c7;font-size:12px;font-weight:600;text-transform:uppercase;border-radius:5px;vertical-align:middle} +.control-treeview a.menu-control:hover, +.control-treeview a.menu-control:focus{text-decoration:none;background-color:#48b2ce;color:#fff;border:none;padding:15px 17px} +.control-treeview a.menu-control:active{background:#6cc551;color:#fff} +.control-treeview a.menu-control i{margin-right:10px;font-size:14px} +.control-treeview.treeview-light{margin-bottom:0;margin-top:20px} +.control-treeview.treeview-light ol{background-color:transparent} +.control-treeview.treeview-light ol>li>div{background-color:transparent;border-bottom:none} +.control-treeview.treeview-light ol>li>div:before{top:15px} +.control-treeview.treeview-light ol>li>div>a{padding-top:10px;padding-bottom:10px} +.control-treeview.treeview-light ol>li>div span.expand{top:19px} +.control-treeview.treeview-light ol>li>div>span.drag-handle{top:0;right:0;bottom:auto;height:100%;width:60px;background:#2581b8;-webkit-transition:none !important;transition:none !important} +.control-treeview.treeview-light ol>li>div>span.drag-handle:before{position:absolute;left:50%;top:50%;margin-left:-6px} +.control-treeview.treeview-light ol>li>div>ul.submenu{right:60px;left:auto;bottom:auto;top:0;height:100%;margin:0;background:transparent;white-space:nowrap;font-size:0} +.control-treeview.treeview-light ol>li>div>ul.submenu:before, +.control-treeview.treeview-light ol>li>div>ul.submenu:after{display:none} +.control-treeview.treeview-light ol>li>div>ul.submenu li{height:100%;display:inline-block;background:#2581b8;border-right:1px solid #328ec8} +.control-treeview.treeview-light ol>li>div>ul.submenu li p{display:table;height:100%;padding:0;margin:0} +.control-treeview.treeview-light ol>li>div>ul.submenu li p a{display:table-cell;vertical-align:middle;height:100%;padding:0 20px;font-size:13px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} +.control-treeview.treeview-light ol>li>div>ul.submenu li p a i.control-icon{font-size:22px;margin-right:0} +body.dragging .control-treeview ol.dragging, +body.dragging .control-treeview ol.dragging ol{background:#ccc;padding-right:0} +body.dragging .control-treeview ol.dragging>li>div, +body.dragging .control-treeview ol.dragging ol>li>div{margin-right:0;-webkit-transition:margin 1s;transition:margin 1s} +body.dragging .control-treeview ol.dragging>li>div .custom-checkbox, +body.dragging .control-treeview ol.dragging ol>li>div .custom-checkbox{-webkit-transition:opacity 0.5s;transition:opacity 0.5s;opacity:0;filter:alpha(opacity=0)} +body.dragging .control-treeview.treeview-light ol.dragging>li>div, +body.dragging .control-treeview.treeview-light ol.dragging ol>li>div{background-color:#f9f9f9} +@media only screen and (min--moz-device-pixel-ratio:1.5),only screen and (-o-min-device-pixel-ratio:1.5),only screen and (-webkit-min-device-pixel-ratio:1.5),only screen and (min-devicepixel-ratio:1.5),only screen and (min-resolution:1.5dppx){.control-treeview ol>li>div:before{background-position:0 -79px;background-size:21px auto}.control-treeview ol>li.has-subitems>div:before{background-position:0 -52px}.control-treeview ol>li.has-subitems>div:hover:before,.control-treeview ol>li.has-subitems>div.popover-highlight:before{background-position:0 -102px}.control-treeview ol>li.dragged>div:before,.control-treeview ol>li.dragged li>div:before,.control-treeview ol>li>div:hover:before,.control-treeview ol>li>div.popover-highlight:before{background-position:0 -129px}.control-treeview ol>li.dragged li.has-subitems>div:before,.control-treeview ol>li.dragged.has-subitems>div:before{background-position:0 -102px}.control-treeview ol>li.drop-target>div:before{background-position:0 -129px}.control-treeview ol>li.drop-target.has-subitems>div:before{background-position:0 -102px}} +.sidenav-tree{width:300px} +.sidenav-tree .control-toolbar{padding:0} +.sidenav-tree .control-toolbar .toolbar-item{display:block} +.sidenav-tree .control-toolbar input.form-control{border:none;outline:none;padding:12px 13px 13px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:inset -3px 0 3px rgba(0,0,0,0.1);box-shadow:inset -3px 0 3px rgba(0,0,0,0.1)} +.sidenav-tree .control-toolbar input.form-control.search{background-position:right -78px} +.sidenav-tree ul{padding:0;margin:0;list-style:none} +.sidenav-tree div.scrollbar-thumb{background:rgba(0,0,0,0.2) !important} +.sidenav-tree ul.top-level>li[data-status=collapsed]>div.group h3:before{-webkit-transform:rotate(0deg) translate(2px,-2px);-ms-transform:rotate(0deg) translate(2px,-2px);transform:rotate(0deg) translate(2px,-2px)} +.sidenav-tree ul.top-level>li[data-status=collapsed]>div.group:before, +.sidenav-tree ul.top-level>li[data-status=collapsed]>div.group:after{display:none} +.sidenav-tree ul.top-level>li[data-status=collapsed] ul{display:none} +.sidenav-tree ul.top-level>li>div.group{position:relative} +.sidenav-tree ul.top-level>li>div.group h3{background:rgba(0,0,0,0.15);color:#ecf0f1;text-transform:uppercase;font-size:15px;padding:15px 15px 15px 40px;margin:0;position:relative;cursor:pointer;font-weight:400} +.sidenav-tree ul.top-level>li>div.group h3:before{display:block;position:absolute;width:10px;height:10px;left:16px;top:15px;color:#cfcfcf;font-family:"Font Awesome 6 Free";font-weight:900;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-style:normal;font-variant:normal;text-rendering:auto;content:"\f105";-webkit-transform:rotate(90deg) translate(5px,-3px);-ms-transform:rotate(90deg) translate(5px,-3px);transform:rotate(90deg) translate(5px,-3px);-webkit-transition:all 0.1s ease;transition:all 0.1s ease;font-size:16px} +.sidenav-tree ul.top-level>li>div.group:before, +.sidenav-tree ul.top-level>li>div.group:after{content:'';display:block;width:0;height:0;border-left:7.5px solid transparent;border-right:7.5px solid transparent;border-top:8px solid #103141;border-bottom-width:0;position:absolute;left:15px;bottom:-8px;z-index:101} +.sidenav-tree ul.top-level>li>div.group:after{content:'';display:block;width:0;height:0;border-left:7.5px solid transparent;border-right:7.5px solid transparent;border-top:8px solid rgba(0,0,0,0.15);border-bottom-width:0} +.sidenav-tree ul.top-level>li>ul li a{display:block;position:relative;padding:18px 25px 18px 55px;background:transparent;border-bottom:1px solid rgba(0,0,0,0.15);color:#fff;text-decoration:none !important;opacity:0.65;filter:alpha(opacity=65)} +.sidenav-tree ul.top-level>li>ul li a:active, +.sidenav-tree ul.top-level>li>ul li a:hover{opacity:1;filter:alpha(opacity=100);text-decoration:none} +.sidenav-tree ul.top-level>li>ul li a i{position:absolute;left:16px;top:18px;font-size:22px} +.sidenav-tree ul.top-level>li>ul li a span{display:block;line-height:150%} +.sidenav-tree ul.top-level>li>ul li a span.header{color:#fff;font-size:15px;margin-bottom:5px} +.sidenav-tree ul.top-level>li>ul li a span.description{color:rgba(255,255,255,0.6);font-size:13px} +.sidenav-tree ul.top-level>li>ul li:hover a, +.sidenav-tree ul.top-level>li>ul li.active a{opacity:1;filter:alpha(opacity=100)} +.sidenav-tree ul.top-level>li>ul li.active{border-left:5px solid #2da7c7} +.sidenav-tree ul.top-level>li>ul li.active a{color:rgba(255,255,255,0.91);padding-right:20px} +.sidenav-tree ul.top-level>li>ul li.active a span.header{color:#fff} +.sidenav-tree ul.top-level>li>ul li.active a span.description{color:rgba(255,255,255,0.91)} +.sidenav-tree .back-link{display:none} +@media (min-width:768px){.sidenav-tree-root .sidenav-tree{width:600px}.sidenav-tree-root .sidenav-tree ul.top-level>li>ul{font-size:0;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-start;align-items:stretch;align-content:stretch}.sidenav-tree-root .sidenav-tree ul.top-level>li>ul>li{display:inline-block;width:300px}.sidenav-tree-root .sidenav-tree ul.top-level>li>ul>li a{height:100%}} +@media (min-width:768px) and (max-width:991px){.sidenav-tree-root .sidenav-tree{width:100%}.sidenav-tree-root .sidenav-tree ul.top-level>li>ul>li{width:50%}} +@media (min-width:1200px){.sidenav-tree-root .sidenav-tree{width:900px}} +@media (max-width:768px){.sidenav-tree{width:100%;height:auto !important;display:block !important}.sidenav-tree>.layout{display:none}.sidenav-tree-root .sidenav-tree{width:100% !important;height:100% !important;display:table-cell !important}.sidenav-tree-root .sidenav-tree .back-link{display:none !important}.sidenav-tree-root .sidenav-tree>.layout{display:table !important}.sidenav-tree-root #layout-body{display:none}body.has-sidenav-tree .sidenav-tree .back-link{display:block;padding:13px 15px;background:#2b3e50;color:#bdc3c7;font-size:14px;line-height:14px;text-transform:uppercase}body.has-sidenav-tree .sidenav-tree .back-link i{display:inline-block;margin-right:10px}body.has-sidenav-tree .sidenav-tree .back-link:hover{text-decoration:none}body.has-sidenav-tree #layout-body{display:block !important}} +div.panel{padding:20px} +div.panel.no-padding{padding:0} +div.panel.no-padding-bottom{padding-bottom:0} +div.panel.padding-top{padding-top:20px} +div.panel.padding-less{padding:15px} +div.panel.transparent{background:transparent} +div.panel.border-left{border-left:1px solid #e8eaeb} +div.panel.border-right{border-right:1px solid #e8eaeb} +div.panel.border-bottom{border-bottom:1px solid #e8eaeb} +div.panel.border-top{border-top:1px solid #e8eaeb} +div.panel.triangle-down{position:relative} +div.panel.triangle-down:after{content:'';display:block;width:0;height:0;border-left:7.5px solid transparent;border-right:7.5px solid transparent;border-top:8px solid white;border-bottom-width:0;position:absolute;left:15px;bottom:-8px;z-index:101} +div.panel.triangle-down:before{content:'';display:block;width:0;height:0;border-left:8.5px solid transparent;border-right:8.5px solid transparent;border-top:9px solid #e8eaeb;border-bottom-width:0;position:absolute;left:14px;bottom:-9px;z-index:100} +div.panel h3.section, +div.panel>label{text-transform:uppercase;color:#95a5a6;font-size:13px;font-weight:600;margin:0 0 15px 0} +div.panel>label{margin-bottom:5px} +.nav.selector-group{font-size:13px;letter-spacing:0.01em;margin-bottom:20px} +.nav.selector-group li a{padding:7px 20px 7px 23px;color:#95a5a6} +.nav.selector-group li.active{border-left:3px solid #e6802b;padding-left:0} +.nav.selector-group li.active a{padding-left:20px;color:#2b3e50} +.nav.selector-group li i[class^="icon-"]{font-size:17px;margin-right:6px;position:relative;top:1px} +div.panel .nav.selector-group{margin:0 -20px 20px -20px} +ul.tree-path{list-style:none;padding:0;margin-bottom:0} +ul.tree-path li{display:inline-block;margin-right:1px;font-size:13px} +ul.tree-path li:after{font-family:"Font Awesome 6 Free";font-weight:900;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-style:normal;font-variant:normal;text-rendering:auto;content:"\f105";display:inline-block;font-size:13px;margin-left:5px;position:relative;top:1px;color:#95a5a6} +ul.tree-path li:last-child a{cursor:default} +ul.tree-path li:last-child:after{display:none} +ul.tree-path li.go-up{font-size:12px;margin-right:7px} +ul.tree-path li.go-up a{color:#95a5a6} +ul.tree-path li.go-up a:hover{color:#2da7c7} +ul.tree-path li.go-up:after{display:none} +ul.tree-path li.root a{font-weight:600;color:#405261} +ul.tree-path li a{color:#95a5a6} +ul.tree-path li a:hover{text-decoration:none} +table.name-value-list{border-collapse:collapse;font-size:13px} +table.name-value-list th, +table.name-value-list td{padding:4px 0 4px 0;vertical-align:top} +table.name-value-list tr:first-child th, +table.name-value-list tr:first-child td{padding-top:0} +table.name-value-list th{font-weight:600;color:#95a5a6;padding-right:15px;text-transform:uppercase} +table.name-value-list td{color:#2b3e50;word-wrap:break-word} +.scrollpad-scrollbar-size-tester{width:50px;height:50px;overflow-y:scroll;position:absolute;top:-200px;left:-200px} +.scrollpad-scrollbar-size-tester div{height:100px} +.scrollpad-scrollbar-size-tester::-webkit-scrollbar{width:0;height:0} +div.control-scrollpad{position:relative;width:100%;height:100%;overflow:hidden} +div.control-scrollpad>div{overflow:hidden;overflow-y:scroll;height:100%} +div.control-scrollpad>div::-webkit-scrollbar{width:0;height:0} +div.control-scrollpad[data-direction=horizontal]>div{overflow-x:scroll;overflow-y:hidden;width:100%} +div.control-scrollpad[data-direction=horizontal]>div::-webkit-scrollbar{width:auto;height:0} +div.control-scrollpad>.scrollpad-scrollbar{z-index:199;position:absolute;top:0;right:0;bottom:0;width:11px;background-color:transparent;opacity:0;overflow:hidden;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;-webkit-transition:opacity 0.3s;transition:opacity 0.3s} +div.control-scrollpad>.scrollpad-scrollbar .drag-handle{position:absolute;right:2px;min-height:10px;width:7px;background-color:rgba(0,0,0,0.35);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px} +div.control-scrollpad>.scrollpad-scrollbar:hover{opacity:0.7;filter:alpha(opacity=70);-webkit-transition:opacity 0 linear;transition:opacity 0 linear} +div.control-scrollpad>.scrollpad-scrollbar[data-visible]{opacity:0.7;filter:alpha(opacity=70)} +div.control-scrollpad>.scrollpad-scrollbar[data-hidden]{display:none} +div.control-scrollpad[data-direction=horizontal]>.scrollpad-scrollbar{top:auto;left:0;width:auto;height:11px} +div.control-scrollpad[data-direction=horizontal]>.scrollpad-scrollbar .drag-handle{right:auto;top:2px;height:7px;min-height:0;min-width:10px;width:auto} +.svg-icon-container img.svg-icon{display:none} +.svg-icon-container.svg-active-effects img.svg-icon{-webkit-filter:grayscale(100%);filter:grayscale(100%);opacity:0.6;filter:alpha(opacity=60)} +.svg-icon-container.svg-active-effects:hover img.svg-icon, +.svg-icon-container.svg-active-effects.active img.svg-icon{-webkit-filter:none;filter:none;opacity:1;filter:alpha(opacity=100)} +html.svg .svg-icon-container i.svg-replace{display:none} +@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}} +@keyframes fadeIn{0%{opacity:0}100%{opacity:1}} +.fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn} +@-webkit-keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}} +@keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);-ms-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}100%{opacity:1;-webkit-transform:none;-ms-transform:none;transform:none}} +.fadeInDown{-webkit-animation-name:fadeInDown;animation-name:fadeInDown} +@-webkit-keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}} +@keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);-ms-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}100%{opacity:1;-webkit-transform:none;-ms-transform:none;transform:none}} +.fadeInLeft{-webkit-animation-name:fadeInLeft;animation-name:fadeInLeft} +@-webkit-keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}} +@keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%,0,0);-ms-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}100%{opacity:1;-webkit-transform:none;-ms-transform:none;transform:none}} +.fadeInRight{-webkit-animation-name:fadeInRight;animation-name:fadeInRight} +@-webkit-keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}} +@keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);-ms-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}100%{opacity:1;-webkit-transform:none;-ms-transform:none;transform:none}} +.fadeInUp{-webkit-animation-name:fadeInUp;animation-name:fadeInUp} +@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}} +@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}} +@keyframes fadeOut{0%{opacity:1}100%{opacity:0}} +.fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut} +@-webkit-keyframes fadeOutDown{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}} +@keyframes fadeOutDown{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,100%,0);-ms-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}} +.fadeOutDown{-webkit-animation-name:fadeOutDown;animation-name:fadeOutDown} +@-webkit-keyframes fadeOutLeft{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}} +@keyframes fadeOutLeft{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-100%,0,0);-ms-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}} +.fadeOutLeft{-webkit-animation-name:fadeOutLeft;animation-name:fadeOutLeft} +@-webkit-keyframes fadeOutRight{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}} +@keyframes fadeOutRight{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0);-ms-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}} +.fadeOutRight{-webkit-animation-name:fadeOutRight;animation-name:fadeOutRight} +@-webkit-keyframes fadeOutUp{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}} +@keyframes fadeOutUp{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-100%,0);-ms-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}} +.fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp} +html:not(.mobile) body.drag *{cursor:grab !important;cursor:-webkit-grab !important;cursor:-moz-grab !important} +body.dragging, +body.dragging *{cursor:move !important} +body.loading, +body.loading *{cursor:wait !important} +body.no-select{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:default !important} +html, +body{height:100%} +body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";background:#f9f9f9;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale} +#layout-canvas{min-height:100%;height:100%} +.control-tabs.primary-tabs>ul.nav-tabs, +.control-tabs.primary-tabs>div>ul.nav-tabs, +.control-tabs.primary-tabs>div>div>ul.nav-tabs{margin-left:-20px;margin-right:-20px} +.control-tabs.primary-tabs.tabs-no-inset>ul.nav-tabs, +.control-tabs.primary-tabs.tabs-no-inset>div>ul.nav-tabs, +.control-tabs.primary-tabs.tabs-no-inset>div>div>ul.nav-tabs{margin-left:0;margin-right:0} +.layout{display:table;table-layout:fixed;height:100%;width:100%} +.layout>.layout-row{display:table-row;vertical-align:top;height:100%} +.layout>.layout-row>.layout-cell{display:table-cell;vertical-align:top;height:100%} +.layout>.layout-row>.layout-cell.layout-container, +.layout>.layout-row>.layout-cell .layout-container, +.layout>.layout-row>.layout-cell.padded-container, +.layout>.layout-row>.layout-cell .padded-container{padding:20px 20px 0 20px} +.layout>.layout-row>.layout-cell.layout-container .container-flush, +.layout>.layout-row>.layout-cell .layout-container .container-flush, +.layout>.layout-row>.layout-cell.padded-container .container-flush, +.layout>.layout-row>.layout-cell .padded-container .container-flush{padding-top:0} +.layout>.layout-row>.layout-cell .layout-relative{position:relative;height:100%} +.layout>.layout-row>.layout-cell .layout-absolute{position:absolute;height:100%;width:100%} +.layout>.layout-row>.layout-cell.min-size{width:0} +.layout>.layout-row>.layout-cell.min-height{height:0} +.layout>.layout-row>.layout-cell.center{text-align:center} +.layout>.layout-row>.layout-cell.middle{vertical-align:middle} +.layout>.layout-row>.layout-cell.layout-container, +.layout>.layout-row>.layout-cell .layout-container, +.layout>.layout-row>.layout-cell.padded-container, +.layout>.layout-row>.layout-cell .padded-container{padding:20px 20px 0 20px} +.layout>.layout-row>.layout-cell.layout-container .container-flush, +.layout>.layout-row>.layout-cell .layout-container .container-flush, +.layout>.layout-row>.layout-cell.padded-container .container-flush, +.layout>.layout-row>.layout-cell .padded-container .container-flush{padding-top:0} +.layout>.layout-row>.layout-cell .layout-relative{position:relative;height:100%} +.layout>.layout-row>.layout-cell .layout-absolute{position:absolute;height:100%;width:100%} +.layout>.layout-row>.layout-cell.min-size{width:0} +.layout>.layout-row>.layout-cell.min-height{height:0} +.layout>.layout-row>.layout-cell.center{text-align:center} +.layout>.layout-row>.layout-cell.middle{vertical-align:middle} +.layout>.layout-row.min-size{height:0.1px} +.layout>.layout-cell{display:table-cell;vertical-align:top;height:100%} +.layout>.layout-cell.layout-container, +.layout>.layout-cell .layout-container, +.layout>.layout-cell.padded-container, +.layout>.layout-cell .padded-container{padding:20px 20px 0 20px} +.layout>.layout-cell.layout-container .container-flush, +.layout>.layout-cell .layout-container .container-flush, +.layout>.layout-cell.padded-container .container-flush, +.layout>.layout-cell .padded-container .container-flush{padding-top:0} +.layout>.layout-cell .layout-relative{position:relative;height:100%} +.layout>.layout-cell .layout-absolute{position:absolute;height:100%;width:100%} +.layout>.layout-cell.min-size{width:0} +.layout>.layout-cell.min-height{height:0} +.layout>.layout-cell.center{text-align:center} +.layout>.layout-cell.middle{vertical-align:middle} +.whiteboard{background:white} +.layout-fill-container{position:absolute;left:0;top:0;width:100%;height:100%} +[data-calculate-width]>form, +[data-calculate-width]>div{display:inline-block} +body.compact-container .layout.layout-container, +body.compact-container .layout .layout-container{padding:0 !important} +body.slim-container .layout.layout-container, +body.slim-container .layout .layout-container{padding-left:0 !important;padding-right:0 !important} +@media (max-width:768px){.layout .hide-on-small{display:none}.layout.responsive-sidebar>.layout-cell:first-child{display:table-footer-group;height:auto}.layout.responsive-sidebar>.layout-cell:first-child .control-breadcrumb{display:none}.layout.responsive-sidebar>.layout-cell:last-child{display:table-header-group;width:auto;height:auto}.layout.responsive-sidebar>.layout-cell:last-child .layout-absolute{position:static}} +@supports (-moz-appearance:none){a:focus:not(:focus-visible){outline:none}} +.flex-layout-column{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flexbox;display:-ms-flex;display:flex;-webkit-flex-direction:column;-moz-flex-direction:column;-webkit-box-orient:vertical;-ms-flex-direction:column;flex-direction:column} +.flex-layout-column.full-height-strict{height:100%} +.flex-layout-column.absolute{position:absolute!important} +.flex-layout-column.fill-container{position:absolute;left:0;top:0;width:100%;height:100%} +.flex-layout-row{display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flexbox;display:-ms-flex;display:flex;-webkit-flex-direction:row;-moz-flex-direction:row;-webkit-box-orient:horizontal;-ms-flex-direction:row;flex-direction:row} +.flex-layout-column.justify-center, +.flex-layout-row.justify-center{-webkit-justify-content:center;-moz-justify-content:center;-ms-justify-content:center;-webkit-box-pack:center;justify-content:center} +.flex-layout-column.align-center, +.flex-layout-row.align-center{-webkit-align-items:center;-moz-align-items:center;-ms-align-items:center;align-items:center;-webkit-align-content:center;-moz-align-content:center;-webkit-box-align:center;-ms-align-content:center;align-content:center} +.flex-layout-column.full-height, +.flex-layout-row.full-height{min-height:100%} +.flex-layout-item{margin:0} +.flex-layout-item.fix{-webkit-box-flex:0;-webkit-flex:0 0 auto;-moz-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto} +.flex-layout-item.stretch{-webkit-box-flex:1;-webkit-flex:1 1 auto;-moz-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto} +.flex-layout-item.stretch-constrain{-webkit-box-flex:1;-webkit-flex:1;-moz-flex:1;-ms-flex:1;flex:1} +.flex-layout-item.center{-webkit-align-self:center;-moz-align-self:center;-ms-align-self:center;align-self:center} +.flex-layout-item.relative{position:relative} +.flex-layout-item.layout-container{max-width:none} +body.mainmenu-open{overflow:hidden;position:fixed} +.mainmenu-tooltip .tooltip-inner{font-size:13px;padding:6px 16px} +ul.mainmenu-nav{font-size:14px} +ul.mainmenu-nav li{} +ul.mainmenu-nav li .svg-icon{-webkit-backface-visibility:hidden;backface-visibility:hidden} +ul.mainmenu-nav li span.counter{display:block;position:absolute;top:0.143em;right:0;padding:0.143em 0.429em 0.214em 0.286em;background-color:#d9350f;color:#fff;font-size:0.786em;line-height:100%;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;opacity:1;filter:alpha(opacity=100);-webkit-transform:scale(1,);-ms-transform:scale(1,);transform:scale(1,);-webkit-transition:all 0.3s;transition:all 0.3s} +ul.mainmenu-nav li span.counter.empty{opacity:0;filter:alpha(opacity=0);-webkit-transform:scale(0,);-ms-transform:scale(0,);transform:scale(0,)} +nav#layout-mainmenu{background-color:#151515;padding:0 0 0 20px;line-height:0;white-space:nowrap;display:flex} +nav#layout-mainmenu a{text-decoration:none} +nav#layout-mainmenu a:focus{background:transparent} +nav#layout-mainmenu ul{margin:0;padding:0;list-style:none;float:left;white-space:nowrap;overflow:hidden} +nav#layout-mainmenu ul li{color:rgba(255,255,255,0.6);display:inline-block;vertical-align:top;position:relative;margin-right:30px} +nav#layout-mainmenu ul li a{display:inline-block;font-size:14px;color:inherit;padding:14px 0 10px} +nav#layout-mainmenu ul li a:hover{background-color:transparent} +nav#layout-mainmenu ul li a:active, +nav#layout-mainmenu ul li a:focus{text-decoration:none;color:rgba(255,255,255,0.6)} +nav#layout-mainmenu ul li a i{line-height:1;font-size:30px;vertical-align:middle} +nav#layout-mainmenu ul li a img.svg-icon{height:30px;width:30px;margin-right:10px;position:relative;top:0} +nav#layout-mainmenu ul.nav{display:inline-block} +nav#layout-mainmenu .toolbar-item{flex:1 1 auto;display:block;padding-right:0;overflow:hidden} +nav#layout-mainmenu .toolbar-item-account{flex:0 0 auto} +nav#layout-mainmenu .toolbar-item:before, +nav#layout-mainmenu .toolbar-item:after{margin-top:0} +nav#layout-mainmenu .toolbar-item:before{left:-12px} +nav#layout-mainmenu .toolbar-item:after{right:-12px} +nav#layout-mainmenu .toolbar-item.scroll-active-before:before{color:#fff} +nav#layout-mainmenu .toolbar-item.scroll-active-after:after{color:#fff} +nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-quick-action{margin:0} +nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-quick-action:first-child{margin-left:21px} +nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-quick-action i{font-size:20px} +nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-quick-action a{position:relative;padding:0 10px;top:-1px} +nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-account{margin-right:0} +nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-account>a{padding:0 15px 0 10px;font-size:13px;position:relative} +nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-account.highlight>a{z-index:600} +nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-account img.account-avatar{width:45px;height:45px} +nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-account .account-name{margin-right:15px} +nav#layout-mainmenu ul.mainmenu-toolbar li.mainmenu-account ul{line-height:23px} +html.svg nav#layout-mainmenu img.svg-icon, +html.svg .mainmenu-collapsed img.svg-icon{display:inline-block} +nav#layout-mainmenu ul li .mainmenu-accountmenu{position:fixed;top:0;right:20px;background:#f9f9f9;z-index:600;display:none;-webkit-box-shadow:0 1px 6px rgba(0,0,0,0.12),0 1px 4px rgba(0,0,0,0.24);box-shadow:0 1px 6px rgba(0,0,0,0.12),0 1px 4px rgba(0,0,0,0.24);border-radius:3px} +nav#layout-mainmenu ul li .mainmenu-accountmenu.active{display:block} +nav#layout-mainmenu ul li .mainmenu-accountmenu:after{content:'';display:block;width:0;height:0;border-left:8.5px solid transparent;border-right:8.5px solid transparent;border-bottom:7px solid #f9f9f9;right:9px;top:-7px;position:absolute} +nav#layout-mainmenu ul li .mainmenu-accountmenu ul{float:none;display:block;overflow:visible} +nav#layout-mainmenu ul li .mainmenu-accountmenu li{padding:0;margin:0;font-weight:normal;text-align:left;display:block} +nav#layout-mainmenu ul li .mainmenu-accountmenu li a{display:block;padding:10px 30px;text-align:left;font-size:14px;color:#666} +nav#layout-mainmenu ul li .mainmenu-accountmenu li a:hover, +nav#layout-mainmenu ul li .mainmenu-accountmenu li a:focus{background:#48b2ce;color:#fff} +nav#layout-mainmenu ul li .mainmenu-accountmenu li a:active{background:#6cc551;color:#fff} +nav#layout-mainmenu ul li .mainmenu-accountmenu li:first-child a:hover:after, +nav#layout-mainmenu ul li .mainmenu-accountmenu li:first-child a:focus:after, +nav#layout-mainmenu ul li .mainmenu-accountmenu li:first-child a:active:after{content:'';display:block;width:0;height:0;border-left:8.5px solid transparent;border-right:8.5px solid transparent;border-bottom:7px solid #48b2ce;position:absolute;right:9px;top:-7px;z-index:102} +nav#layout-mainmenu ul li .mainmenu-accountmenu li:first-child a:active:after{content:'';display:block;width:0;height:0;border-left:8.5px solid transparent;border-right:8.5px solid transparent;border-bottom:7px solid #6cc551} +nav#layout-mainmenu ul li .mainmenu-accountmenu li.divider{height:1px;width:100%;background-color:#e0e0e0} +nav#layout-mainmenu.navbar-mode-inline, +nav#layout-mainmenu.navbar-mode-inline_no_icons{height:60px} +nav#layout-mainmenu.navbar-mode-inline ul.mainmenu-toolbar li.mainmenu-quick-action a, +nav#layout-mainmenu.navbar-mode-inline_no_icons ul.mainmenu-toolbar li.mainmenu-quick-action a{height:60px;line-height:60px} +nav#layout-mainmenu.navbar-mode-inline ul.mainmenu-toolbar li.mainmenu-account>a, +nav#layout-mainmenu.navbar-mode-inline_no_icons ul.mainmenu-toolbar li.mainmenu-account>a{height:60px;line-height:60px} +nav#layout-mainmenu.navbar-mode-inline ul li .mainmenu-accountmenu, +nav#layout-mainmenu.navbar-mode-inline_no_icons ul li .mainmenu-accountmenu{top:70px} +nav#layout-mainmenu.navbar-mode-inline ul.mainmenu-nav li, +nav#layout-mainmenu.navbar-mode-inline_no_icons ul.mainmenu-nav li{margin:5px 0} +nav#layout-mainmenu.navbar-mode-inline ul.mainmenu-nav li a, +nav#layout-mainmenu.navbar-mode-inline_no_icons ul.mainmenu-nav li a{padding:10px 15px} +nav#layout-mainmenu.navbar-mode-inline ul.mainmenu-nav li a .nav-icon, +nav#layout-mainmenu.navbar-mode-inline_no_icons ul.mainmenu-nav li a .nav-icon{position:relative;top:-1px;margin-right:5px;width:30px;height:30px} +nav#layout-mainmenu.navbar-mode-inline ul.mainmenu-nav li a .nav-icon i, +nav#layout-mainmenu.navbar-mode-inline_no_icons ul.mainmenu-nav li a .nav-icon i, +nav#layout-mainmenu.navbar-mode-inline ul.mainmenu-nav li a .nav-icon img, +nav#layout-mainmenu.navbar-mode-inline_no_icons ul.mainmenu-nav li a .nav-icon img{margin:0} +nav#layout-mainmenu.navbar-mode-inline ul.mainmenu-nav li a .nav-label, +nav#layout-mainmenu.navbar-mode-inline_no_icons ul.mainmenu-nav li a .nav-label{line-height:30px} +nav#layout-mainmenu.navbar-mode-inline ul.mainmenu-nav li:first-child, +nav#layout-mainmenu.navbar-mode-inline_no_icons ul.mainmenu-nav li:first-child{margin-left:-13px} +nav#layout-mainmenu.navbar-mode-inline ul.mainmenu-nav li:last-child, +nav#layout-mainmenu.navbar-mode-inline_no_icons ul.mainmenu-nav li:last-child{margin-right:0} +nav#layout-mainmenu.navbar-mode-inline_no_icons .nav-icon{display:none !important} +nav#layout-mainmenu.navbar-mode-tile{height:78px} +nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-toolbar li.mainmenu-quick-action a{height:78px;line-height:78px} +nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-toolbar li.mainmenu-account>a{height:78px;line-height:78px} +nav#layout-mainmenu.navbar-mode-tile ul li .mainmenu-accountmenu{top:88px} +nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li a{position:relative;width:65px;height:65px} +nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li a .nav-icon{text-align:center;display:block;position:absolute;top:50%;left:50%;margin-left:-15px;margin-top:-26.5px;width:30px;height:30px} +nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li a .nav-icon i, +nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li a .nav-icon img{margin:0} +nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li a .nav-label{display:block;width:100px;height:20px;line-height:20px;position:absolute;bottom:4px;left:50%;padding:0 5px;margin-left:-50px;overflow:hidden;text-overflow:ellipsis;text-align:center} +nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li{padding:0 15px;margin:7px 0 0} +nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li:first-child{margin-left:-7px} +nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li:hover .nav-label{width:auto;min-width:100px;text-overflow:all;overflow:visible;z-index:2} +nav#layout-mainmenu.navbar-mode-tile ul.mainmenu-nav li.active:first-child{margin-left:0} +nav#layout-mainmenu .menu-toggle{height:45px;line-height:45px;font-size:16px;display:none} +nav#layout-mainmenu .menu-toggle .menu-toggle-icon{background:#333;display:inline-block;height:45px;line-height:45px;width:45px;text-align:center;opacity:0.7} +nav#layout-mainmenu .menu-toggle .menu-toggle-icon i{line-height:45px;font-size:20px;vertical-align:bottom} +nav#layout-mainmenu .menu-toggle .menu-toggle-title{margin-left:10px} +nav#layout-mainmenu .menu-toggle:hover .menu-toggle-icon{opacity:1} +body.mainmenu-open nav#layout-mainmenu .menu-toggle-icon{opacity:1} +nav#layout-mainmenu.navbar-mode-collapse{padding-left:0;height:45px} +nav#layout-mainmenu.navbar-mode-collapse ul.mainmenu-toolbar li.mainmenu-quick-action a{height:45px;line-height:45px} +nav#layout-mainmenu.navbar-mode-collapse ul.mainmenu-toolbar li.mainmenu-account>a{height:45px;line-height:45px} +nav#layout-mainmenu.navbar-mode-collapse ul li .mainmenu-accountmenu{top:55px} +nav#layout-mainmenu.navbar-mode-collapse ul.mainmenu-toolbar li.mainmenu-account>a{padding-right:0} +nav#layout-mainmenu.navbar-mode-collapse ul li .mainmenu-accountmenu:after{right:13px} +nav#layout-mainmenu.navbar-mode-collapse ul.nav{display:none} +nav#layout-mainmenu.navbar-mode-collapse .menu-toggle{display:inline-block;color:#fff !important} +@media (max-width:769px){nav#layout-mainmenu.navbar{padding-left:0;height:45px}nav#layout-mainmenu.navbar ul.mainmenu-toolbar li.mainmenu-quick-action a{height:45px;line-height:45px}nav#layout-mainmenu.navbar ul.mainmenu-toolbar li.mainmenu-account>a{height:45px;line-height:45px}nav#layout-mainmenu.navbar ul li .mainmenu-accountmenu{top:55px}nav#layout-mainmenu.navbar ul.mainmenu-toolbar li.mainmenu-account>a{padding-right:0}nav#layout-mainmenu.navbar ul li .mainmenu-accountmenu:after{right:13px}nav#layout-mainmenu.navbar ul.nav{display:none}nav#layout-mainmenu.navbar .menu-toggle{display:inline-block;color:#fff !important}} +.mainmenu-collapsed{position:absolute;height:100%;top:0;left:0;margin:0;background:#000} +.mainmenu-collapsed>div{display:block;height:100%} +.mainmenu-collapsed>div ul.mainmenu-nav li a{position:relative;width:65px;height:65px} +.mainmenu-collapsed>div ul.mainmenu-nav li a .nav-icon{text-align:center;display:block;position:absolute;top:50%;left:50%;margin-left:-15px;margin-top:-26.5px;width:30px;height:30px} +.mainmenu-collapsed>div ul.mainmenu-nav li a .nav-icon i, +.mainmenu-collapsed>div ul.mainmenu-nav li a .nav-icon img{margin:0} +.mainmenu-collapsed>div ul.mainmenu-nav li a .nav-label{display:block;width:100px;height:20px;line-height:20px;position:absolute;bottom:4px;left:50%;padding:0 5px;margin-left:-50px;overflow:hidden;text-overflow:ellipsis;text-align:center} +.mainmenu-collapsed>div ul.mainmenu-nav li{padding:0 15px;margin:7px 0 0} +.mainmenu-collapsed>div ul.mainmenu-nav li:first-child{margin-left:-7px} +.mainmenu-collapsed>div ul.mainmenu-nav li:hover .nav-label{width:auto;min-width:100px;text-overflow:all;overflow:visible;z-index:2} +.mainmenu-collapsed>div ul.mainmenu-nav li.active:first-child{margin-left:0} +.mainmenu-collapsed>div ul.mainmenu-nav li:first-child{margin-left:0} +.mainmenu-collapsed>div ul{margin:0;padding:5px 0 15px 15px;overflow:hidden} +.mainmenu-collapsed>div ul li{color:rgba(255,255,255,0.6);display:inline-block;vertical-align:top;position:relative;margin-right:30px} +.mainmenu-collapsed>div ul li a{display:inline-block;font-size:14px;color:inherit} +.mainmenu-collapsed>div ul li a:hover{background-color:transparent} +.mainmenu-collapsed>div ul li a:active, +.mainmenu-collapsed>div ul li a:focus{text-decoration:none;color:rgba(255,255,255,0.6)} +.mainmenu-collapsed>div ul li a i{line-height:1;font-size:30px;vertical-align:middle} +.mainmenu-collapsed>div ul li a img.svg-icon{height:30px;width:30px;position:relative;top:0} +.mainmenu-collapsed .scroll-marker{position:absolute;left:0;width:100%;height:10px;display:none} +.mainmenu-collapsed .scroll-marker:after{font-family:"Font Awesome 6 Free";font-weight:900;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-style:normal;font-variant:normal;text-rendering:auto;content:"\f141";display:block;position:absolute;left:50%;margin-left:-3px;top:0;height:9px;font-size:10px;color:rgba(255,255,255,0.6)} +.mainmenu-collapsed .scroll-marker.before{top:0} +.mainmenu-collapsed .scroll-marker.after{bottom:3px} +.mainmenu-collapsed .scroll-marker.after:after{top:2px} +.mainmenu-collapsed.scroll-before .scroll-marker.before{display:block} +.mainmenu-collapsed.scroll-after .scroll-marker.after{display:block} +body.mainmenu-open .mainmenu-collapsed ul{position:absolute;left:0;top:10px;bottom:10px} +html.mobile .mainmenu-collapsed ul{overflow:auto;-webkit-overflow-scrolling:touch} +nav#layout-mainmenu.navbar ul li:hover a:active, +.mainmenu-collapsed li:hover a:active, +nav#layout-mainmenu.navbar ul li:hover a:focus, +.mainmenu-collapsed li:hover a:focus{color:#fff !important} +.touch .mainmenu-collapsed li a:hover{color:rgba(255,255,255,0.6)} +nav#layout-mainmenu.navbar ul li.highlight>a, +.mainmenu-collapsed li.highlight>a{color:#fff !important} +nav#layout-mainmenu.navbar ul li.active, +.mainmenu-collapsed li.active{color:#fff !important} +nav#layout-mainmenu.navbar ul li.active a, +.mainmenu-collapsed li.active a{color:#fff !important} +nav#layout-mainmenu.navbar ul li:hover, +.mainmenu-collapsed li:hover{color:#fff;background:transparent} +body.drag nav#layout-mainmenu.navbar ul.nav li:hover, +body.drag .mainmenu-collapsed ul li:hover{color:rgba(255,255,255,0.6)} +.layout-sidenav-container{width:120px} +#layout-sidenav{position:absolute;height:100%;width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;font-size:14px} +#layout-sidenav ul{position:relative;margin:0;padding:0;height:100%;overflow:hidden} +#layout-sidenav ul li{display:block;text-align:center;position:relative} +#layout-sidenav ul li a{padding:1.429em 0.714em;display:block;font-size:0.929em;color:rgba(255,255,255,0.6);font-weight:normal;position:relative} +#layout-sidenav ul li a:hover{text-decoration:none;background-color:transparent} +#layout-sidenav ul li a:focus{background:transparent} +#layout-sidenav ul li a i{color:rgba(255,255,255,0.6);display:block;margin-bottom:5px;font-size:2em} +#layout-sidenav ul li:first-child a{padding-top:2.143em} +#layout-sidenav ul li.active a, +#layout-sidenav ul li a:hover{color:#fff} +#layout-sidenav ul li.active a i, +#layout-sidenav ul li a:hover i{color:#fff} +#layout-sidenav ul li span.counter{display:block;position:absolute;top:1.071em;right:1.071em;padding:0.143em 0.429em 0.214em 0.286em;background-color:#d9350f;color:#fff;font-size:0.786em;line-height:100%;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;opacity:1;filter:alpha(opacity=100);-webkit-transform:scale(1,);-ms-transform:scale(1,);transform:scale(1,);-webkit-transition:all 0.3s;transition:all 0.3s} +#layout-sidenav ul li span.counter.empty{opacity:0;filter:alpha(opacity=0);-webkit-transform:scale(0,);-ms-transform:scale(0,);transform:scale(0,)} +@media (min-width:768px) and (max-width:991px){#layout-sidenav{font-size:12px}.layout-sidenav-container{width:100px}} +@media (max-width:767px){#layout-sidenav{font-size:10px}.layout-sidenav-container{width:80px}} +html.mobile #layout-sidenav ul{overflow:auto;-webkit-overflow-scrolling:touch} +#layout-sidenav.layout-sidenav ul.drag li:not(.active) a:hover, +.touch #layout-sidenav.layout-sidenav li:not(.active) a:hover{color:rgba(255,255,255,0.6) !important} +#layout-sidenav.layout-sidenav ul.drag li:not(.active) a:hover i, +.touch #layout-sidenav.layout-sidenav li:not(.active) a:hover i{color:rgba(255,255,255,0.6) !important} +#layout-sidenav.layout-sidenav ul.drag li:not(.active) a:hover:after, +.touch #layout-sidenav.layout-sidenav li:not(.active) a:hover:after{display:none !important} +#layout-side-panel .fix-button{position:absolute;right:-25px;top:0;display:none;width:25px;height:25px;font-size:13px;background:#ecf0f1;z-index:120;opacity:0.5;filter:alpha(opacity=50);-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0} +#layout-side-panel .fix-button i{display:block;text-align:center;margin-top:5px;color:#aaa} +#layout-side-panel .fix-button:hover{text-decoration:none;display:block;opacity:1 !important;filter:alpha(opacity=100) !important} +#layout-side-panel:hover .fix-button{display:block} +#layout-side-panel .fix-button-content-header .fix-button{top:46px} +#layout-side-panel .sidepanel-content-header{background:#2896b2;color:white;font-size:15px;padding:12px 20px 13px;position:relative} +#layout-side-panel .sidepanel-content-header:after{content:'';display:block;width:0;height:0;border-left:7.5px solid transparent;border-right:7.5px solid transparent;border-top:8px solid #2896b2;border-bottom-width:0;position:absolute;left:14px;bottom:-8px} +body.side-panel-not-fixed #layout-side-panel{display:none} +body.side-panel-not-fixed #layout-side-panel .fix-button{opacity:0.5;filter:alpha(opacity=50)} +body.display-side-panel #layout-side-panel{display:block;position:absolute;z-index:600;width:350px;-webkit-box-shadow:3px 0 3px 0 rgba(0,0,0,0.1);box-shadow:3px 0 3px 0 rgba(0,0,0,0.1)} +@media (min-width:992px){body.side-panel-fix-shadow #layout-side-panel{-webkit-box-shadow:none;box-shadow:none}} +.touch #layout-side-panel .fix-button{display:none} +@media (max-width:768px){#layout-side-panel .fix-button{display:none}} +#layout-footer{width:100%;z-index:100;height:60px;position:fixed;bottom:0;color:#666;background-color:rgba(255,255,255,0.8);border-top:1px solid #dfdfdf} +#layout-footer .brand, +#layout-footer .tagline{margin:10px;height:40px;line-height:40px} +#layout-footer .brand{float:left;font-size:16px} +#layout-footer .brand .logo{margin:0 10px} +#layout-footer .tagline{float:right} +#layout-footer .tagline p{color:#999} +body.outer{background:#2b3e50} +body.outer .layout>.layout-row.layout-head{text-align:center;background:#f9f9f9} +body.outer .layout>.layout-row.layout-head>.layout-cell{height:40%;padding:50px 0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;vertical-align:middle;position:relative} +body.outer .layout>.layout-row.layout-head>.layout-cell:after{content:'';display:block;width:0;height:0;border-left:28px solid transparent;border-right:28px solid transparent;border-top:20px solid #f9f9f9;border-bottom-width:0;position:absolute;bottom:-20px;left:50%;margin-left:-28px} +body.outer .layout>.layout-row.layout-head>.layout-cell h1.wn-logo, +body.outer .layout>.layout-row.layout-head>.layout-cell h1.oc-logo{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0;display:inline-block;width:100%;max-width:450px;height:170px;min-height:72px} +body.outer .layout>.layout-row>.layout-cell{vertical-align:top} +body.outer .layout>.layout-row>.layout-cell .outer-form-container{margin:0 auto;width:436px;padding:40px 0} +body.outer .layout>.layout-row>.layout-cell .outer-form-container h2{font-size:18px;margin:20px 0;color:#feffff} +body.outer .layout>.layout-row>.layout-cell .outer-form-container .horizontal-form{font-size:0;display:-webkit-box;display:-webkit-flex;display:-moz-flex;display:-ms-flexbox;display:-ms-flex;display:flex} +body.outer .layout>.layout-row>.layout-cell .outer-form-container .horizontal-form input{vertical-align:top;margin-right:9px;display:inline-block;border:none;-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px} +body.outer .layout>.layout-row>.layout-cell .outer-form-container .horizontal-form button{background:#2da7c7;text-align:center;font-size:13px;font-weight:600;height:40px;vertical-align:top;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box} +body.outer .layout>.layout-row>.layout-cell .outer-form-container .remember label{color:rgba(255,255,255,0.44)} +body.outer .layout>.layout-row>.layout-cell .outer-form-container .remember input#remember{display:none} +body.outer .layout>.layout-row>.layout-cell .outer-form-container .forgot-password{margin-top:30px;font-size:13px;top:8px} +body.outer .layout>.layout-row>.layout-cell .outer-form-container .forgot-password a{color:rgba(255,255,255,0.44)} +body.outer .layout>.layout-row>.layout-cell .outer-form-container .forgot-password:before{color:rgba(255,255,255,0.44);font-size:14px;position:relative;margin-right:5px} +html.csstransitions body.outer .outer-form-container{-webkit-transition:all 0.5s ease-out;transition:all 0.5s ease-out;-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-ms-transform:scale(1,1);-o-transform:scale(1,1);transform:scale(1,1)} +html.csstransitions body.outer.preload .outer-form-container{-webkit-transform:scale(0.2,0.2);-moz-transform:scale(0.2,0.2);-ms-transform:scale(0.2,0.2);-o-transform:scale(0.2,0.2);transform:scale(0.2,0.2)} +@media (max-width:768px){body.outer .layout>.layout-row.layout-head>.layout-cell{padding:50px 20px}body.outer .layout>.layout-row>.layout-cell .outer-form-container{width:auto;padding:40px}body.outer .layout>.layout-row>.layout-cell .outer-form-container .horizontal-form{display:block}body.outer .layout>.layout-row>.layout-cell .outer-form-container .horizontal-form input{display:block;width:100% !important;margin-bottom:20px}} +body.fancy-layout .master-tabs.control-tabs, +.master-tabs.control-tabs.fancy-layout{overflow:hidden} +body.fancy-layout .master-tabs.control-tabs:before, +.master-tabs.control-tabs.fancy-layout:before, +body.fancy-layout .master-tabs.control-tabs:after, +.master-tabs.control-tabs.fancy-layout:after{top:13px;font-size:14px;color:rgba(255,255,255,0.35)} +body.fancy-layout .master-tabs.control-tabs:before, +.master-tabs.control-tabs.fancy-layout:before{left:8px} +body.fancy-layout .master-tabs.control-tabs:after, +.master-tabs.control-tabs.fancy-layout:after{right:8px} +body.fancy-layout .master-tabs.control-tabs.scroll-before:before, +.master-tabs.control-tabs.fancy-layout.scroll-before:before{color:#fff} +body.fancy-layout .master-tabs.control-tabs.scroll-after:after, +.master-tabs.control-tabs.fancy-layout.scroll-after:after{color:#fff} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container{background:#2896b2;padding-left:20px;padding-right:20px} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs{margin-left:-8px} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li{margin-left:-5px;top:1px;padding-top:3px} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li span.tab-close, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li span.tab-close{top:14px;right:-3px;left:auto;z-index:110;font-family:sans-serif} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li span.tab-close i, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li span.tab-close i{top:4px;right:1px;color:rgba(255,255,255,0.3) !important;font-style:normal;font-weight:bold;font-size:16px} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li span.tab-close i:hover, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li span.tab-close i:hover{color:#fff !important} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li a, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li a{border-bottom:none;background:transparent;font-size:14px;color:rgba(255,255,255,0.35);padding:6px 0 0 24px!important;overflow:visible} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li a>span.title, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li a>span.title{position:relative;display:inline-block;padding:12px 5px 0 5px;height:38px;font-size:14px;z-index:100;background-color:#2c9cb9} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li a>span.title:before, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li a>span.title:before, +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li a>span.title:after, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li a>span.title:after{content:' ';position:absolute;width:20px;display:block;height:37px;top:0;z-index:100;background-color:#2c9cb9} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li a>span.title:before, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li a>span.title:before{left:-14px;-webkit-border-radius:8px 0 0 0;-moz-border-radius:8px 0 0 0;border-radius:8px 0 0 0;-webkit-transform:skewX(-20deg);-ms-transform:skewX(-20deg);transform:skewX(-20deg)} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li a>span.title:after, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li a>span.title:after{right:-14px;-webkit-border-radius:0 8px 0 0;-moz-border-radius:0 8px 0 0;border-radius:0 8px 0 0;-webkit-transform:skewX(20deg);-ms-transform:skewX(20deg);transform:skewX(20deg)} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li a>span.title span, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li a>span.title span{border-top:none;padding:0;margin-top:0;overflow:visible} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li a:before, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li a:before{z-index:110;position:absolute;top:18px;left:22px} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li a[class*=icon]>span.title, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li a[class*=icon]>span.title{padding-left:18px} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li.active a, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li.active a{z-index:107;color:#fff} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li.active span.tab-close i, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li.active span.tab-close i{color:#fff} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li.active a>span.title, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li.active a>span.title{background-color:#2da7c7;z-index:105} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li.active a>span.title:before, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li.active a>span.title:before{z-index:107;background-color:#2da7c7} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li.active a>span.title:after, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li.active a>span.title:after{background-color:#2da7c7;z-index:107} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li[data-modified] span.tab-close i, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li[data-modified] span.tab-close i{top:5px;font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li[data-modified] span.tab-close i:before, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li[data-modified] span.tab-close i:before{font-family:"Font Awesome 6 Free";font-weight:900;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-style:normal;font-variant:normal;text-rendering:auto;content:"\f111";font-size:9px} +body.fancy-layout .master-tabs.control-tabs>div>div.tabs-container>ul.nav-tabs>li:first-child, +.master-tabs.control-tabs.fancy-layout>div>div.tabs-container>ul.nav-tabs>li:first-child{margin-left:0} +body.fancy-layout .master-tabs.control-tabs[data-closable]>div>div.tabs-container>ul.nav-tabs>li a>span.title, +.master-tabs.control-tabs.fancy-layout[data-closable]>div>div.tabs-container>ul.nav-tabs>li a>span.title{padding-right:10px} +body.fancy-layout .master-tabs.control-tabs.has-tabs:before, +.master-tabs.control-tabs.fancy-layout.has-tabs:before, +body.fancy-layout .master-tabs.control-tabs.has-tabs:after, +.master-tabs.control-tabs.fancy-layout.has-tabs:after{display:block} +body.fancy-layout .master-tabs.control-tabs.has-tabs>div.tab-content, +.master-tabs.control-tabs.fancy-layout.has-tabs>div.tab-content{background:#f9f9f9} +body.fancy-layout .master-tabs.control-tabs>.tab-content>.tab-pane, +.master-tabs.control-tabs.fancy-layout>.tab-content>.tab-pane{padding:0} +body.fancy-layout .master-tabs.control-tabs>.tab-content>.tab-pane.padded-pane, +.master-tabs.control-tabs.fancy-layout>.tab-content>.tab-pane.padded-pane{padding:20px 20px 0 20px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs.master-area>div>ul.nav-tabs, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs.master-area>div>ul.nav-tabs{-webkit-transition:background-color 0.5s;transition:background-color 0.5s;background:#2da7c7} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs{background:#7F8C8D;margin-left:0!important;margin-right:0!important} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs:before, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs:before{display:none} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs>li{background:transparent;border-right:none;margin-right:-8px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li:first-child, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs>li:first-child{margin-left:-5px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li a, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs>li a{background:transparent;border:none;padding:12px 16px 0;font-size:14px;font-weight:400;color:#95a5a6} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li a span.title, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs>li a span.title{background:#d5d9d8;border-top:none;padding:5px 5px 3px 5px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li a span.title:before, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs>li a span.title:before, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li a span.title:after, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs>li a span.title:after{background:#d5d9d8;border-width:0;top:0} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li a span.title:before, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs>li a span.title:before{left:-20px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li a span.title:after, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs>li a span.title:after{right:-20px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li a span.title span, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs>li a span.title span{border-width:0;vertical-align:top} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li.active a, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs>li.active a{color:#808c8d} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li.active a:before, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs>li.active a:before{display:none} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li.active a span.title, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs>li.active a span.title{background:#fafafa} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li.active a span.title:before, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs>li.active a span.title:before, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>div>ul.nav-tabs>li.active a span.title:after, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>div>ul.nav-tabs>li.active a span.title:after{background:#fafafa} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>.tab-content>.tab-pane, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>.tab-content>.tab-pane{padding:20px 20px 0 20px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs>.tab-content>.tab-pane.pane-compact, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs>.tab-content>.tab-pane.pane-compact{padding:0} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs.collapsed, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs.collapsed{display:none} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.primary-tabs.has-tabs>div.tab-content, +*:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.fancy-layout.primary-tabs.has-tabs>div.tab-content{background:#f9f9f9} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs:before{left:5px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs:after{right:5px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs>div>ul.nav-tabs{background:#475354} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs>div>ul.nav-tabs>li{border-right:none;padding-right:0;margin-right:0} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs>div>ul.nav-tabs>li a{background:transparent;border:none;padding:12px 10px 13px 10px;font-size:14px;font-weight:normal;line-height:14px;color:#919898} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs>div>ul.nav-tabs>li a span span{overflow:visible;border-top:none;margin-top:0;padding-top:0} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs>div>ul.nav-tabs>li:first-child{padding-left:15px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs>div>ul.nav-tabs>li.active a{color:#fff} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs .tab-collapse-icon{position:absolute;display:block;text-decoration:none;outline:none;opacity:0.6;filter:alpha(opacity=60);-webkit-transition:all 0.3s;transition:all 0.3s;font-size:12px;color:#fff;right:11px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs .tab-collapse-icon:hover{text-decoration:none;opacity:1;filter:alpha(opacity=100)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs .tab-collapse-icon.primary{color:#fff;top:12px;right:11px;bottom:auto;z-index:100;-webkit-transform:scale(1,-1);-moz-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs .tab-collapse-icon.primary i{position:relative;display:block} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.primary-collapsed .tab-collapse-icon.primary{-webkit-transform:scale(1,1);-moz-transform:scale(1,1);-ms-transform:scale(1,1);-o-transform:scale(1,1);transform:scale(1,1)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs{background:#f9f9f9} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li{margin-left:-19px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li:first-child{margin-left:0;padding-left:8px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li a{padding:8px 16px 0 16px;font-weight:400;height:36px;color:#2b3e50;opacity:0.6;filter:alpha(opacity=60)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li a>span.title{position:relative;display:inline-block;padding:8px 5px 9px 5px;font-size:14px;z-index:100;height:27px!important;background-color:transparent} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li a>span.title:before, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li a>span.title:after{content:' ';position:absolute;background-color:white;width:15px;height:28px;top:0;z-index:100;display:none} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li a>span.title:before{left:-11px;-webkit-border-radius:8px 0 0 0;-moz-border-radius:8px 0 0 0;border-radius:8px 0 0 0;-webkit-transform:skewX(-20deg);-ms-transform:skewX(-20deg);transform:skewX(-20deg)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li a>span.title:after{right:-11px;-webkit-border-radius:0 8px 0 0;-moz-border-radius:0 8px 0 0;border-radius:0 8px 0 0;-webkit-transform:skewX(20deg);-ms-transform:skewX(20deg);transform:skewX(20deg)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li a>span.title span{height:18px;font-size:14px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li.active a{opacity:1;filter:alpha(opacity=100)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li.active a>span.title{background-color:white} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li.active a>span.title:before, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs>div>ul.nav-tabs>li.active a>span.title:after{display:block} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs .tab-collapse-icon.primary{color:#000} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs.primary-collapsed .tab-collapse-icon.primary{color:#fff} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs.primary-collapsed>div>ul.nav-tabs{background:#2da7c7} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs.primary-collapsed>div>ul.nav-tabs>li a{color:white} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs.primary-collapsed>div>ul.nav-tabs>li a>span.title:before, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs.primary-collapsed>div>ul.nav-tabs>li a>span.title:after{background-color:white} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.secondary-content-tabs.primary-collapsed>div>ul.nav-tabs>li.active a{color:#2b3e50} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs.has-tabs>div.tab-content{background:#f9f9f9} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs>.tab-content>.tab-pane{padding:0} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-tabs>.tab-content>.tab-pane.padded-pane{padding:20px 20px 0 20px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields{position:relative;background:#2da7c7;padding:18px 23px 0 23px;-webkit-transition:all 0.5s;transition:all 0.5s} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields:before, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields:after{content:" ";display:table} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields:after{clear:both} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields label{text-transform:uppercase;color:rgba(255,255,255,0.5);margin-bottom:0} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .form-control[disabled]{background-color:rgba(29,29,29,0.11) !important} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields input[type=text]{background:transparent;border:none;color:#fff;font-size:35px;font-weight:100;height:auto;padding:0;-webkit-box-shadow:none;box-shadow:none} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields input[type=text]::-moz-placeholder{color:rgba(255,255,255,0.5);opacity:1} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields input[type=text]:-ms-input-placeholder{color:rgba(255,255,255,0.5)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields input[type=text]::-webkit-input-placeholder{color:rgba(255,255,255,0.5)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields input[type=text]:focus, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields input[type=text]:hover{background-color:rgba(255,255,255,0.1)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .form-group{padding-bottom:0} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .form-group.is-required>label:after{display:none} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .tab-collapse-icon{position:absolute;display:block;text-decoration:none;outline:none;opacity:0.6;filter:alpha(opacity=60);-webkit-transition:all 0.3s;transition:all 0.3s;font-size:12px;color:#fff;right:11px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .tab-collapse-icon:hover{text-decoration:none;opacity:1;filter:alpha(opacity=100)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .tab-collapse-icon.primary{color:#fff;top:12px;right:11px;bottom:auto;z-index:100;-webkit-transform:scale(1,-1);-moz-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .tab-collapse-icon.primary i{position:relative;display:block} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .tab-collapse-icon.tabless{top:14px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields.collapsed{padding:5px 23px 0 10px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields.collapsed .tab-collapse-icon.tabless{-webkit-transform:scale(1,-1);-moz-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields.collapsed .form-group:not(.collapse-visible){display:none} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields.collapsed .form-buttons{margin-left:10px;padding-bottom:0} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .loading-indicator-container .loading-indicator{background-color:#2da7c7;padding:0 0 0 30px;color:rgba(255,255,255,0.5);margin-top:1px;height:90%;font-size:12px;line-height:100%} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .loading-indicator-container .loading-indicator>span{left:-10px;top:18px} +body.breadcrumb-fancy .control-breadcrumb, +.control-breadcrumb.breadcrumb-fancy{margin-bottom:0;background-color:#1198bc} +body.breadcrumb-fancy .control-breadcrumb li, +.control-breadcrumb.breadcrumb-fancy li{background-color:#0e7d9a;color:rgba(255,255,255,0.5)} +body.breadcrumb-fancy .control-breadcrumb li a, +.control-breadcrumb.breadcrumb-fancy li a{opacity:0.5;-webkit-transition:all 0.3s ease;transition:all 0.3s ease} +body.breadcrumb-fancy .control-breadcrumb li a:hover, +.control-breadcrumb.breadcrumb-fancy li a:hover{opacity:1} +body.breadcrumb-fancy .control-breadcrumb li:not(:last-child)::before, +.control-breadcrumb.breadcrumb-fancy li:not(:last-child)::before{border-left-color:#2da7c7;opacity:0.5} +body.breadcrumb-fancy .control-breadcrumb li:after, +.control-breadcrumb.breadcrumb-fancy li:after{border-left-color:#0e7d9a} +body.breadcrumb-fancy .control-breadcrumb li:last-child, +.control-breadcrumb.breadcrumb-fancy li:last-child{background-color:#1198bc} +body.breadcrumb-fancy .control-breadcrumb li:last-child:before, +.control-breadcrumb.breadcrumb-fancy li:last-child:before{opacity:1;border-left-color:#1198bc} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs .form-buttons:not(.normalized), +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .form-buttons:not(.normalized){-webkit-transition:all 0.5s;transition:all 0.5s;padding-top:14px;padding-bottom:5px} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs .form-buttons:not(.normalized) .btn, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .form-buttons:not(.normalized) .btn{padding:0;margin-right:5px;margin-top:-6px;margin-right:30px;background:transparent;color:#fff;font-weight:normal;-webkit-box-shadow:none;box-shadow:none;opacity:0.5;filter:alpha(opacity=50);-webkit-transition:all 0.3s ease;transition:all 0.3s ease} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs .form-buttons:not(.normalized) .btn:hover, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .form-buttons:not(.normalized) .btn:hover{opacity:1;filter:alpha(opacity=100)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs .form-buttons:not(.normalized) .btn:last-child, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .form-buttons:not(.normalized) .btn:last-child{margin-right:0} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs .form-buttons:not(.normalized) .btn[class^="wn-icon-"]:before, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .form-buttons:not(.normalized) .btn[class^="wn-icon-"]:before, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs .form-buttons:not(.normalized) .btn[class*=" wn-icon-"]:before, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .form-buttons:not(.normalized) .btn[class*=" wn-icon-"]:before, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs .form-buttons:not(.normalized) .btn[class^="oc-icon-"]:before, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .form-buttons:not(.normalized) .btn[class^="oc-icon-"]:before, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs .form-buttons:not(.normalized) .btn[class*=" oc-icon-"]:before, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .form-buttons:not(.normalized) .btn[class*=" oc-icon-"]:before{opacity:1} +.fancy-layout form[class$="-data-changed"] *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs .btn.save{opacity:1;filter:alpha(opacity=100)} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs>.tab-content>.tab-pane>.form-group>.field-codeeditor{border:none !important;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs>.tab-content>.tab-pane>.form-group>.field-codeeditor .editor-code{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs>.tab-content>.tab-pane>.form-group>.field-richeditor{border:none;border-left:1px solid #d1d6d9 !important} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs>.tab-content>.tab-pane>.form-group>.field-richeditor, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs>.tab-content>.tab-pane>.form-group>.field-richeditor .fr-toolbar, +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs>.tab-content>.tab-pane>.form-group>.field-richeditor .fr-wrapper{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;border-top-right-radius:0;border-top-left-radius:0} +.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs.secondary-content-tabs>.tab-content>.tab-pane>.form-group>.field-richeditor .fr-toolbar{background:white} +body.side-panel-not-fixed .fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs>.tab-content>.tab-pane>.form-group>.field-richeditor, +body.side-panel-not-fixed.fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.control-tabs>.tab-content>.tab-pane>.form-group>.field-richeditor{border-left:none} +html.cssanimations .fancy-layout *:not(.nested-form):not(.modal-body)>.form-widget>.layout-row>.form-tabless-fields .loading-indicator-container .loading-indicator>span{-webkit-animation:spin 1s linear infinite;animation:spin 1s linear infinite;background-image:url('../../../system/assets/ui/images/loader-white.svg');background-size:20px 20px} +.flyout-container>.flyout{overflow:hidden;width:0;left:0!important;-webkit-transition:width 0.1s;transition:width 0.1s} +.flyout-overlay{width:100%;height:100%;top:0;z-index:5000;position:absolute;background-color:rgba(0,0,0,0);-webkit-transition:background-color 0.3s;transition:background-color 0.3s} +.flyout-toggle{position:absolute;top:20px;left:0;width:23px;height:25px;background:#2b3e50;cursor:pointer;border-bottom-right-radius:4px;border-top-right-radius:4px;color:#bdc3c7;font-size:10px} +.flyout-toggle i{margin:7px 0 0 6px;display:inline-block} +.flyout-toggle:hover i{color:#fff} +body.flyout-visible{overflow:hidden} +body.flyout-visible .flyout-overlay{background-color:rgba(0,0,0,0.3)} +/* Record navigation (formcontroller/partials/_record_navigation.php) */ +.control-breadcrumb{position:relative} +.form-record-nav{position:absolute;top:0;bottom:0;right:20px;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;gap:9px;font-size:12px} +.form-record-nav .form-record-nav-position{color:#5a6b7b;font-weight:600;letter-spacing:.3px;white-space:nowrap} +.form-record-nav .form-record-nav-group{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;background:rgba(255,255,255,.55);border:1px solid rgba(0,0,0,.09);border-radius:6px;overflow:hidden;box-shadow:0 1px 1px rgba(0,0,0,.03)} +.form-record-nav .form-record-nav-btn{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-align:center;-webkit-align-items:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;width:28px;height:24px;color:#5a6b7b;text-decoration:none;-webkit-transition:background-color .12s ease,color .12s ease;transition:background-color .12s ease,color .12s ease} +.form-record-nav .form-record-nav-btn+.form-record-nav-btn{border-left:1px solid rgba(0,0,0,.09)} +.form-record-nav .form-record-nav-btn:not(.is-disabled):hover{background-color:#fff;color:#1f2d3d} +.form-record-nav .form-record-nav-btn.is-disabled{color:#b6bfc7;cursor:default} +.form-record-nav .form-record-nav-btn svg{display:block} diff --git a/modules/backend/assets/images/dashboard-icon.svg b/modules/backend/assets/images/dashboard-icon.svg new file mode 100644 index 0000000..abdd52d --- /dev/null +++ b/modules/backend/assets/images/dashboard-icon.svg @@ -0,0 +1,17 @@ + + + + dashboard-icon + Created with Sketch. + + + + + + + + + + + + diff --git a/modules/backend/assets/images/favicon.png b/modules/backend/assets/images/favicon.png new file mode 100644 index 0000000..2a14a9f Binary files /dev/null and b/modules/backend/assets/images/favicon.png differ diff --git a/modules/backend/assets/images/logo.svg b/modules/backend/assets/images/logo.svg new file mode 100644 index 0000000..9d202b9 --- /dev/null +++ b/modules/backend/assets/images/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/backend/assets/images/media-icon.svg b/modules/backend/assets/images/media-icon.svg new file mode 100644 index 0000000..3723217 --- /dev/null +++ b/modules/backend/assets/images/media-icon.svg @@ -0,0 +1,22 @@ + + + + media-icon + Created with Sketch. + + + + + + + + + + + + + + + + + diff --git a/modules/backend/assets/images/secondary-tab-shape-content.svg b/modules/backend/assets/images/secondary-tab-shape-content.svg new file mode 100644 index 0000000..164511a --- /dev/null +++ b/modules/backend/assets/images/secondary-tab-shape-content.svg @@ -0,0 +1,16 @@ + + + +]> + + + + + + + + diff --git a/modules/backend/assets/images/tab-shape.svg b/modules/backend/assets/images/tab-shape.svg new file mode 100644 index 0000000..0645c36 --- /dev/null +++ b/modules/backend/assets/images/tab-shape.svg @@ -0,0 +1,16 @@ + + + +]> + + + + + + + + + diff --git a/modules/backend/assets/images/treeview-icons.png b/modules/backend/assets/images/treeview-icons.png new file mode 100644 index 0000000..a08c70b Binary files /dev/null and b/modules/backend/assets/images/treeview-icons.png differ diff --git a/modules/backend/assets/images/treeview-submenu-tabs.png b/modules/backend/assets/images/treeview-submenu-tabs.png new file mode 100644 index 0000000..6c39867 Binary files /dev/null and b/modules/backend/assets/images/treeview-submenu-tabs.png differ diff --git a/modules/backend/assets/images/winter-logo-white.svg b/modules/backend/assets/images/winter-logo-white.svg new file mode 100644 index 0000000..e072730 --- /dev/null +++ b/modules/backend/assets/images/winter-logo-white.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/modules/backend/assets/images/winter-logo.svg b/modules/backend/assets/images/winter-logo.svg new file mode 100644 index 0000000..18c85e7 --- /dev/null +++ b/modules/backend/assets/images/winter-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/backend/assets/images/wordmark.png b/modules/backend/assets/images/wordmark.png new file mode 100644 index 0000000..3b2280d Binary files /dev/null and b/modules/backend/assets/images/wordmark.png differ diff --git a/modules/backend/assets/js/auth/auth.js b/modules/backend/assets/js/auth/auth.js new file mode 100644 index 0000000..caa70f0 --- /dev/null +++ b/modules/backend/assets/js/auth/auth.js @@ -0,0 +1,5 @@ +$(document).ready(function(){ + $(document.body).removeClass('preload') + + $('form input[type=text], form input[type=password]').first().focus() +}) \ No newline at end of file diff --git a/modules/backend/assets/js/backend.js b/modules/backend/assets/js/backend.js new file mode 100644 index 0000000..f8898d6 --- /dev/null +++ b/modules/backend/assets/js/backend.js @@ -0,0 +1,102 @@ +/* + * Winter General Utilities + */ + +/* + * Path helpers + */ + +if ($.wn === undefined) + $.wn = {} +if ($.oc === undefined) + $.oc = $.wn + +$.wn.backendUrl = function(url) { + var backendBasePath = $('meta[name="backend-base-path"]').attr('content') + + if (!backendBasePath) + return url + + if (url.substr(0, 1) == '/') + url = url.substr(1) + + return backendBasePath + '/' + url +} + +/* + * String escape + */ +if ($.wn === undefined) + $.wn = {} +if ($.oc === undefined) + $.oc = $.wn + +$.wn.escapeHtmlString = function(string) { + var htmlEscapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/' + }, + htmlEscaper = /[&<>"'\/]/g + + return ('' + string).replace(htmlEscaper, function(match) { + return htmlEscapes[match]; + }) +} + +/* + * Inverse Click Event (not used) + * + * Calls the handler function if the user has clicked outside the object + * and not on any of the elements in the exception list. + */ +/* +$.fn.extend({ + clickOutside: function(handler, exceptions) { + var $this = this; + + $('body').on('click', function(event) { + if (exceptions && $.inArray(event.target, exceptions) > -1) { + return; + } else if ($.contains($this[0], event.target)) { + return; + } else { + handler(event, $this); + } + }); + + return this; + } +}) +*/ + +/* + * Browser Fixes + * - If another fix using JS is necessary, move this logic to backend.fixes.js + */ + +/* + * Internet Explorer v11 + * - IE11 will not honor height 100% when overflow is used on the Y axis. + */ +if (!!window.MSInputMethodContext && !!document.documentMode) { + $(window).on('resize', function() { + fixMediaManager() + fixSidebar() + }) + + function fixMediaManager() { + var $el = $('div[data-control="media-manager"] .control-scrollpad') + $el.height($el.parent().height()) + } + + function fixSidebar() { + $('#layout-sidenav').height(Math.max( + $('#layout-body').innerHeight(), + $(window).height() - $('#layout-mainmenu').height() + )) + } +} diff --git a/modules/backend/assets/js/preferences/preferences.js b/modules/backend/assets/js/preferences/preferences.js new file mode 100644 index 0000000..b8049d7 --- /dev/null +++ b/modules/backend/assets/js/preferences/preferences.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk_wintercms_wn_backend_module=self.webpackChunk_wintercms_wn_backend_module||[]).push([[429],{449:function(e,t,i){var n=i(171);(e=>{class t extends e.Singleton{construct(){this.widget=null}listens(){return{"backend.widget.initialized":"onWidgetInitialized"}}onWidgetInitialized(e,t){e===document.getElementById("CodeEditor-formEditorPreview-_editor_preview")&&(this.widget=t,this.enablePreferences())}enablePreferences(){(0,n.M)("change");Object.entries({show_gutter:"showGutter",highlight_active_line:"highlightActiveLine",use_hard_tabs:"!useSoftTabs",display_indent_guides:"displayIndentGuides",show_invisibles:"showInvisibles",show_print_margin:"showPrintMargin",show_minimap:"showMinimap",enable_folding:"codeFolding",bracket_colors:"bracketColors",show_colors:"showColors"}).forEach(([e,t])=>{this.element(e).addEventListener("change",e=>{this.widget.setConfig(t.replace(/^!/,""),/^!/.test(t)?!e.target.checked:e.target.checked)})}),this.element("theme").addEventListener("$change",e=>{this.widget.loadTheme(e.target.value)}),this.element("font_size").addEventListener("$change",e=>{this.widget.setConfig("fontSize",e.target.value)}),this.element("tab_size").addEventListener("$change",e=>{this.widget.setConfig("tabSize",e.target.value)}),this.element("word_wrap").addEventListener("$change",e=>{const{value:t}=e.target;switch(t){case"off":this.widget.setConfig("wordWrap",!1);break;case"fluid":this.widget.setConfig("wordWrap","fluid");break;default:this.widget.setConfig("wordWrap",parseInt(t,10))}}),document.querySelectorAll("[data-switch-lang]").forEach(e=>{e.addEventListener("click",t=>{t.preventDefault();const i=e.dataset.switchLang,n=document.querySelector(`[data-lang-snippet="${i}"]`);n&&(this.widget.setValue(n.textContent.trim()),this.widget.setLanguage(i))})}),this.widget.events.once("create",()=>{const e=new MouseEvent("click");document.querySelector('[data-switch-lang="css"]').dispatchEvent(e)})}element(e){return document.getElementById(`Form-field-Preference-editor_${e}`)}}e.addPlugin("backend.preferences",t)})(window.Snowboard)}},function(e){e.O(0,[810],function(){return t=449,e(e.s=t);var t});e.O()}]); \ No newline at end of file diff --git a/modules/backend/assets/js/vendor/jquery-and-migrate.min.js b/modules/backend/assets/js/vendor/jquery-and-migrate.min.js new file mode 100644 index 0000000..04ba79a --- /dev/null +++ b/modules/backend/assets/js/vendor/jquery-and-migrate.min.js @@ -0,0 +1,5 @@ +/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},M=function(){V()},R=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&U(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&R(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,r.msMatchesSelector&&ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",M),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|&#?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="
",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return M(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return M(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 0\x20\t\r\n\f]*)[^>]*)\/>/gi;s.UNSAFE_restoreLegacyHtmlPrefilter=function(){s.migrateEnablePatches("self-closed-tags")},i(s,"htmlPrefilter",function(e){var t,r;return(r=(t=e).replace(F,"<$1>"))!==t&&T(t)!==T(r)&&u("self-closed-tags","HTML tags must be properly nested and closed: "+t),e.replace(F,"<$1>")},"self-closed-tags"),s.migrateDisablePatches("self-closed-tags");var D,W,_,I=s.fn.offset;return i(s.fn,"offset",function(){var e=this[0];return!e||e.nodeType&&e.getBoundingClientRect?I.apply(this,arguments):(u("offset-valid-elem","jQuery.fn.offset() requires a valid DOM element"),arguments.length?this:void 0)},"offset-valid-elem"),s.ajax&&(D=s.param,i(s,"param",function(e,t){var r=s.ajaxSettings&&s.ajaxSettings.traditional;return void 0===t&&r&&(u("param-ajax-traditional","jQuery.param() no longer uses jQuery.ajaxSettings.traditional"),t=r),D.call(this,e,t)},"param-ajax-traditional")),c(s.fn,"andSelf",s.fn.addBack,"andSelf","jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()"),s.Deferred&&(W=s.Deferred,_=[["resolve","done",s.Callbacks("once memory"),s.Callbacks("once memory"),"resolved"],["reject","fail",s.Callbacks("once memory"),s.Callbacks("once memory"),"rejected"],["notify","progress",s.Callbacks("memory"),s.Callbacks("memory")]],i(s,"Deferred",function(e){var a=W(),i=a.promise();function t(){var o=arguments;return s.Deferred(function(n){s.each(_,function(e,t){var r="function"==typeof o[e]&&o[e];a[t[1]](function(){var e=r&&r.apply(this,arguments);e&&"function"==typeof e.promise?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[t[0]+"With"](this===i?n.promise():this,r?[e]:arguments)})}),o=null}).promise()}return c(a,"pipe",t,"deferred-pipe","deferred.pipe() is deprecated"),c(i,"pipe",t,"deferred-pipe","deferred.pipe() is deprecated"),e&&e.call(a,a),a},"deferred-pipe"),s.Deferred.exceptionHook=W.exceptionHook),s}); diff --git a/modules/backend/assets/js/vendor/jquery-migrate.min.js b/modules/backend/assets/js/vendor/jquery-migrate.min.js new file mode 100644 index 0000000..29a4939 --- /dev/null +++ b/modules/backend/assets/js/vendor/jquery-migrate.min.js @@ -0,0 +1,2 @@ +/*! jQuery Migrate v3.4.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +"undefined"==typeof jQuery.migrateMute&&(jQuery.migrateMute=!0),function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e,window)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery"),window):t(jQuery,window)}(function(s,n){"use strict";function e(e){return 0<=function(e,t){for(var r=/^(\d+)\.(\d+)\.(\d+)/,n=r.exec(e)||[],o=r.exec(t)||[],a=1;a<=3;a++){if(+o[a]<+n[a])return 1;if(+n[a]<+o[a])return-1}return 0}(s.fn.jquery,e)}s.migrateVersion="3.4.1";var t=Object.create(null);s.migrateDisablePatches=function(){for(var e=0;e\x20\t\r\n\f]*)[^>]*)\/>/gi;s.UNSAFE_restoreLegacyHtmlPrefilter=function(){s.migrateEnablePatches("self-closed-tags")},i(s,"htmlPrefilter",function(e){var t,r;return(r=(t=e).replace(F,"<$1>"))!==t&&T(t)!==T(r)&&u("self-closed-tags","HTML tags must be properly nested and closed: "+t),e.replace(F,"<$1>")},"self-closed-tags"),s.migrateDisablePatches("self-closed-tags");var D,W,_,I=s.fn.offset;return i(s.fn,"offset",function(){var e=this[0];return!e||e.nodeType&&e.getBoundingClientRect?I.apply(this,arguments):(u("offset-valid-elem","jQuery.fn.offset() requires a valid DOM element"),arguments.length?this:void 0)},"offset-valid-elem"),s.ajax&&(D=s.param,i(s,"param",function(e,t){var r=s.ajaxSettings&&s.ajaxSettings.traditional;return void 0===t&&r&&(u("param-ajax-traditional","jQuery.param() no longer uses jQuery.ajaxSettings.traditional"),t=r),D.call(this,e,t)},"param-ajax-traditional")),c(s.fn,"andSelf",s.fn.addBack,"andSelf","jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()"),s.Deferred&&(W=s.Deferred,_=[["resolve","done",s.Callbacks("once memory"),s.Callbacks("once memory"),"resolved"],["reject","fail",s.Callbacks("once memory"),s.Callbacks("once memory"),"rejected"],["notify","progress",s.Callbacks("memory"),s.Callbacks("memory")]],i(s,"Deferred",function(e){var a=W(),i=a.promise();function t(){var o=arguments;return s.Deferred(function(n){s.each(_,function(e,t){var r="function"==typeof o[e]&&o[e];a[t[1]](function(){var e=r&&r.apply(this,arguments);e&&"function"==typeof e.promise?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[t[0]+"With"](this===i?n.promise():this,r?[e]:arguments)})}),o=null}).promise()}return c(a,"pipe",t,"deferred-pipe","deferred.pipe() is deprecated"),c(i,"pipe",t,"deferred-pipe","deferred.pipe() is deprecated"),e&&e.call(a,a),a},"deferred-pipe"),s.Deferred.exceptionHook=W.exceptionHook),s}); diff --git a/modules/backend/assets/js/vendor/jquery.autoellipsis.js b/modules/backend/assets/js/vendor/jquery.autoellipsis.js new file mode 100644 index 0000000..7bd28ef --- /dev/null +++ b/modules/backend/assets/js/vendor/jquery.autoellipsis.js @@ -0,0 +1,447 @@ +/*! + + Copyright (c) 2011 Peter van der Spek + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + */ + + +(function($) { + + /** + * Hash containing mapping of selectors to settings hashes for target selectors that should be live updated. + * + * @type {Object.} + * @private + */ + var liveUpdatingTargetSelectors = {}; + + /** + * Interval ID for live updater. Contains interval ID when the live updater interval is active, or is undefined + * otherwise. + * + * @type {number} + * @private + */ + var liveUpdaterIntervalId; + + /** + * Boolean indicating whether the live updater is running. + * + * @type {boolean} + * @private + */ + var liveUpdaterRunning = false; + + /** + * Set of default settings. + * + * @type {Object.} + * @private + */ + var defaultSettings = { + ellipsis: '...', + setTitle: 'never', + live: false + }; + + /** + * Perform ellipsis on selected elements. + * + * @param {string} selector the inner selector of elements that ellipsis may work on. Inner elements not referred to by this + * selector are left untouched. + * @param {Object.=} options optional options to override default settings. + * @return {jQuery} the current jQuery object for chaining purposes. + * @this {jQuery} the current jQuery object. + */ + $.fn.ellipsis = function(selector, options) { + var subjectElements, settings; + + subjectElements = $(this); + + // Check for options argument only. + if (typeof selector !== 'string') { + options = selector; + selector = undefined; + } + + // Create the settings from the given options and the default settings. + settings = $.extend({}, defaultSettings, options); + + // If selector is not set, work on immediate children (default behaviour). + settings.selector = selector; + + // Do ellipsis on each subject element. + subjectElements.each(function() { + var elem = $(this); + + // Do ellipsis on subject element. + ellipsisOnElement(elem, settings); + }); + + // If live option is enabled, add subject elements to live updater. Otherwise remove from live updater. + if (settings.live) { + addToLiveUpdater(subjectElements.selector, settings); + + } else { + removeFromLiveUpdater(subjectElements.selector); + } + + // Return jQuery object for chaining. + return this; + }; + + + /** + * Perform ellipsis on the given container. + * + * @param {jQuery} containerElement jQuery object containing one DOM element to perform ellipsis on. + * @param {Object.} settings the settings for this ellipsis operation. + * @private + */ + function ellipsisOnElement(containerElement, settings) { + var containerData = containerElement.data('jqae'); + if (!containerData) containerData = {}; + + // Check if wrapper div was already created and bound to the container element. + var wrapperElement = containerData.wrapperElement; + + // If not, create wrapper element. + if (!wrapperElement) { + wrapperElement = containerElement.wrapInner('
').find('>div'); + + // Wrapper div should not add extra size. + wrapperElement.css({ + margin: 0, + padding: 0, + border: 0 + }); + } + + // Check if the original wrapper element content was already bound to the wrapper element. + var wrapperElementData = wrapperElement.data('jqae'); + if (!wrapperElementData) wrapperElementData = {}; + + var wrapperOriginalContent = wrapperElementData.originalContent; + + // If so, clone the original content, re-bind the original wrapper content to the clone, and replace the + // wrapper with the clone. + if (wrapperOriginalContent) { + wrapperElement = wrapperElementData.originalContent.clone(true) + .data('jqae', {originalContent: wrapperOriginalContent}).replaceAll(wrapperElement); + + } else { + // Otherwise, clone the current wrapper element and bind it as original content to the wrapper element. + + wrapperElement.data('jqae', {originalContent: wrapperElement.clone(true)}); + } + + // Bind the wrapper element and current container width and height to the container element. Current container + // width and height are stored to detect changes to the container size. + containerElement.data('jqae', { + wrapperElement: wrapperElement, + containerWidth: containerElement.width(), + containerHeight: containerElement.height() + }); + + // Calculate with current container element height. + var containerElementHeight = containerElement.height(); + + // Calculate wrapper offset. + var wrapperOffset = (parseInt(containerElement.css('padding-top'), 10) || 0) + (parseInt(containerElement.css('border-top-width'), 10) || 0) - (wrapperElement.offset().top - containerElement.offset().top); + + // Normally the ellipsis characters are applied to the last non-empty text-node in the selected element. If the + // selected element becomes empty during ellipsis iteration, the ellipsis characters cannot be applied to that + // selected element, and must be deferred to the previous selected element. This parameter keeps track of that. + var deferAppendEllipsis = false; + + // Loop through all selected elements in reverse order. + var selectedElements = wrapperElement; + if (settings.selector) selectedElements = $(wrapperElement.find(settings.selector).get().reverse()); + + selectedElements.each(function() { + var selectedElement = $(this), + originalText = selectedElement.text(), + ellipsisApplied = false; + + // Check if we can safely remove the selected element. This saves a lot of unnecessary iterations. + if (wrapperElement.innerHeight() - selectedElement.innerHeight() > containerElementHeight + wrapperOffset) { + selectedElement.remove(); + + } else { + // Reverse recursively remove empty elements, until the element that contains a non-empty text-node. + removeLastEmptyElements(selectedElement); + + // If the selected element has not become empty, start ellipsis iterations on the selected element. + if (selectedElement.contents().length) { + + // If a deffered ellipsis is still pending, apply it now to the last text-node. + if (deferAppendEllipsis) { + getLastTextNode(selectedElement).get(0).nodeValue += settings.ellipsis; + deferAppendEllipsis = false; + } + + // Iterate until wrapper element height is less than or equal to the original container element + // height plus possible wrapperOffset. + while (wrapperElement.innerHeight() > containerElementHeight + wrapperOffset) { + // Apply ellipsis on last text node, by removing one word. + ellipsisApplied = ellipsisOnLastTextNode(selectedElement); + + // If ellipsis was succesfully applied, remove any remaining empty last elements and append the + // ellipsis characters. + if (ellipsisApplied) { + removeLastEmptyElements(selectedElement); + + // If the selected element is not empty, append the ellipsis characters. + if (selectedElement.contents().length) { + getLastTextNode(selectedElement).get(0).nodeValue += settings.ellipsis; + + } else { + // If the selected element has become empty, defer the appending of the ellipsis characters + // to the previous selected element. + deferAppendEllipsis = true; + selectedElement.remove(); + break; + } + + } else { + // If ellipsis could not be applied, defer the appending of the ellipsis characters to the + // previous selected element. + deferAppendEllipsis = true; + selectedElement.remove(); + break; + } + } + + // If the "setTitle" property is set to "onEllipsis" and the ellipsis has been applied, or if the + // property is set to "always", the add the "title" attribute with the original text. Else remove the + // "title" attribute. When the "setTitle" property is set to "never" we do not touch the "title" + // attribute. + if (((settings.setTitle == 'onEllipsis') && ellipsisApplied) || (settings.setTitle == 'always')) { + selectedElement.attr('title', originalText); + + } else if (settings.setTitle != 'never') { + selectedElement.removeAttr('title'); + } + } + } + }); + } + + /** + * Performs ellipsis on the last text node of the given element. Ellipsis is done by removing a full word. + * + * @param {jQuery} element jQuery object containing a single DOM element. + * @return {boolean} true when ellipsis has been done, false otherwise. + * @private + */ + function ellipsisOnLastTextNode(element) { + var lastTextNode = getLastTextNode(element); + + // If the last text node is found, do ellipsis on that node. + if (lastTextNode.length) { + var text = lastTextNode.get(0).nodeValue; + + // Find last space character, and remove text from there. If no space is found the full remaining text is + // removed. + var pos = text.lastIndexOf(' '); + if (pos > -1) { + text = $.trim(text.substring(0, pos)); + lastTextNode.get(0).nodeValue = text; + + } else { + lastTextNode.get(0).nodeValue = ''; + } + + return true; + } + + return false; + } + + /** + * Get last text node of the given element. + * + * @param {jQuery} element jQuery object containing a single element. + * @return {jQuery} jQuery object containing a single text node. + * @private + */ + function getLastTextNode(element) { + if (element.contents().length) { + + // Get last child node. + var contents = element.contents(); + var lastNode = contents.eq(contents.length - 1); + + // If last node is a text node, return it. + if (lastNode.filter(textNodeFilter).length) { + return lastNode; + + } else { + // Else it is an element node, and we recurse into it. + + return getLastTextNode(lastNode); + } + + } else { + // If there is no last child node, we append an empty text node and return that. Normally this should not + // happen, as we test for emptiness before calling getLastTextNode. + + element.append(''); + var contents = element.contents(); + return contents.eq(contents.length - 1); + } + } + + /** + * Remove last empty elements. This is done recursively until the last element contains a non-empty text node. + * + * @param {jQuery} element jQuery object containing a single element. + * @return {boolean} true when elements have been removed, false otherwise. + * @private + */ + function removeLastEmptyElements(element) { + if (element.contents().length) { + + // Get last child node. + var contents = element.contents(); + var lastNode = contents.eq(contents.length - 1); + + // If last child node is a text node, check for emptiness. + if (lastNode.filter(textNodeFilter).length) { + var text = lastNode.get(0).nodeValue; + text = $.trim(text); + + if (text == '') { + // If empty, remove the text node. + lastNode.remove(); + + return true; + + } else { + return false; + } + + } else { + // If the last child node is an element node, remove the last empty child nodes on that node. + while (removeLastEmptyElements(lastNode)) { + } + + // If the last child node contains no more child nodes, remove the last child node. + if (lastNode.contents().length) { + return false; + + } else { + lastNode.remove(); + + return true; + } + } + } + + return false; + } + + /** + * Filter for testing on text nodes. + * + * @return {boolean} true when this node is a text node, false otherwise. + * @this {Node} + * @private + */ + function textNodeFilter() { + return this.nodeType === 3; + } + + /** + * Add target selector to hash of target selectors. If this is the first target selector added, start the live + * updater. + * + * @param {string} targetSelector the target selector to run the live updater for. + * @param {Object.} settings the settings to apply on this target selector. + * @private + */ + function addToLiveUpdater(targetSelector, settings) { + // Store target selector with its settings. + liveUpdatingTargetSelectors[targetSelector] = settings; + + // If the live updater has not yet been started, start it now. + if (!liveUpdaterIntervalId) { + liveUpdaterIntervalId = window.setInterval(function() { + doLiveUpdater(); + }, 200); + } + } + + /** + * Remove the target selector from the hash of target selectors. It this is the last remaining target selector + * being removed, stop the live updater. + * + * @param {string} targetSelector the target selector to stop running the live updater for. + * @private + */ + function removeFromLiveUpdater(targetSelector) { + // If the hash contains the target selector, remove it. + if (liveUpdatingTargetSelectors[targetSelector]) { + delete liveUpdatingTargetSelectors[targetSelector]; + + // If no more target selectors are in the hash, stop the live updater. + if (!liveUpdatingTargetSelectors.length) { + if (liveUpdaterIntervalId) { + window.clearInterval(liveUpdaterIntervalId); + liveUpdaterIntervalId = undefined; + } + } + } + }; + + /** + * Run the live updater. The live updater is periodically run to check if its monitored target selectors require + * re-applying of the ellipsis. + * + * @private + */ + function doLiveUpdater() { + // If the live updater is already running, skip this time. We only want one instance running at a time. + if (!liveUpdaterRunning) { + liveUpdaterRunning = true; + + // Loop through target selectors. + for (var targetSelector in liveUpdatingTargetSelectors) { + $(targetSelector).each(function() { + var containerElement, containerData; + + containerElement = $(this); + containerData = containerElement.data('jqae'); + + // If container element dimensions have changed, or the container element is new, run ellipsis on + // that container element. + if ((containerData.containerWidth != containerElement.width()) || + (containerData.containerHeight != containerElement.height())) { + ellipsisOnElement(containerElement, liveUpdatingTargetSelectors[targetSelector]); + } + }); + } + + liveUpdaterRunning = false; + } + }; + +})(jQuery); \ No newline at end of file diff --git a/modules/backend/assets/js/vendor/jquery.cookie.js b/modules/backend/assets/js/vendor/jquery.cookie.js new file mode 100644 index 0000000..feb62e9 --- /dev/null +++ b/modules/backend/assets/js/vendor/jquery.cookie.js @@ -0,0 +1,117 @@ +/*! + * jQuery Cookie Plugin v1.4.1 + * https://github.com/carhartl/jquery-cookie + * + * Copyright 2006, 2014 Klaus Hartl + * Released under the MIT license + */ +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD + define(['jquery'], factory); + } else if (typeof exports === 'object') { + // CommonJS + factory(require('jquery')); + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + + var pluses = /\+/g; + + function encode(s) { + return config.raw ? s : encodeURIComponent(s); + } + + function decode(s) { + return config.raw ? s : decodeURIComponent(s); + } + + function stringifyCookieValue(value) { + return encode(config.json ? JSON.stringify(value) : String(value)); + } + + function parseCookieValue(s) { + if (s.indexOf('"') === 0) { + // This is a quoted cookie as according to RFC2068, unescape... + s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\'); + } + + try { + // Replace server-side written pluses with spaces. + // If we can't decode the cookie, ignore it, it's unusable. + // If we can't parse the cookie, ignore it, it's unusable. + s = decodeURIComponent(s.replace(pluses, ' ')); + return config.json ? JSON.parse(s) : s; + } catch(e) {} + } + + function read(s, converter) { + var value = config.raw ? s : parseCookieValue(s); + return $.isFunction(converter) ? converter(value) : value; + } + + var config = $.cookie = function (key, value, options) { + + // Write + + if (arguments.length > 1 && !$.isFunction(value)) { + options = $.extend({}, config.defaults, options); + + if (typeof options.expires === 'number') { + var days = options.expires, t = options.expires = new Date(); + t.setTime(+t + days * 864e+5); + } + + return (document.cookie = [ + encode(key), '=', stringifyCookieValue(value), + options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE + options.path ? '; path=' + options.path : '', + options.domain ? '; domain=' + options.domain : '', + options.secure ? '; secure' : '' + ].join('')); + } + + // Read + + var result = key ? undefined : {}; + + // To prevent the for loop in the first place assign an empty array + // in case there are no cookies at all. Also prevents odd result when + // calling $.cookie(). + var cookies = document.cookie ? document.cookie.split('; ') : []; + + for (var i = 0, l = cookies.length; i < l; i++) { + var parts = cookies[i].split('='); + var name = decode(parts.shift()); + var cookie = parts.join('='); + + if (key && key === name) { + // If second argument (value) is a function it's a converter... + result = read(cookie, value); + break; + } + + // Prevent storing a cookie that we couldn't decode. + if (!key && (cookie = read(cookie)) !== undefined) { + result[name] = cookie; + } + } + + return result; + }; + + config.defaults = {}; + + $.removeCookie = function (key, options) { + if ($.cookie(key) === undefined) { + return false; + } + + // Must not alter options, thus extending a fresh object... + $.cookie(key, '', $.extend({}, options, { expires: -1 })); + return !$.cookie(key); + }; + +})); diff --git a/modules/backend/assets/js/vendor/jquery.min.js b/modules/backend/assets/js/vendor/jquery.min.js new file mode 100644 index 0000000..7f37b5d --- /dev/null +++ b/modules/backend/assets/js/vendor/jquery.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},M=function(){V()},R=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&U(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&R(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,r.msMatchesSelector&&ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",M),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|&#?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="
",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return M(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return M(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 0= config.min_move_x) { + cancelTouch(); + if(dx > 0) { + config.wipeLeft(); + } + else { + config.wipeRight(); + } + } + else if(Math.abs(dy) >= config.min_move_y) { + cancelTouch(); + if(dy > 0) { + config.wipeDown(); + } + else { + config.wipeUp(); + } + } + } + } + + function onTouchStart(e) + { + if (e.touches.length == 1) { + startX = e.touches[0].pageX; + startY = e.touches[0].pageY; + isMoving = true; + this.addEventListener('touchmove', onTouchMove, false); + } + } + if ('ontouchstart' in document.documentElement) { + this.addEventListener('touchstart', onTouchStart, false); + } + }); + + return this; + }; + + })(jQuery); \ No newline at end of file diff --git a/modules/backend/assets/js/vendor/jquery.waterfall.js b/modules/backend/assets/js/vendor/jquery.waterfall.js new file mode 100644 index 0000000..a27b6fb --- /dev/null +++ b/modules/backend/assets/js/vendor/jquery.waterfall.js @@ -0,0 +1,63 @@ +(function($) { +/** + * Runs functions given in arguments in series, each functions passing their results to the next one. + * Return jQuery Deferred object. + * + * @example + * $.waterfall( + * function() { return $.ajax({url : first_url}) }, + * function() { return $.ajax({url : second_url}) }, + * function() { return $.ajax({url : another_url}) } + *).fail(function() { + * console.log(arguments) + *).done(function() { + * console.log(arguments) + *}) + * + * @example2 + * event_chain = []; + * event_chain.push(function() { var deferred = $.Deferred(); deferred.resolve(); return deferred; }); + * $.waterfall.apply(this, event_chain).fail(function(){}).done(function(){}); + * + * @author Dmitry (dio) Levashov, dio@std42.ru + * @return jQuery.Deferred + */ +$.waterfall = function() { + var steps = [], + dfrd = $.Deferred(), + pointer = 0; + + $.each(arguments, function(i, a) { + steps.push(function() { + var args = [].slice.apply(arguments), d; + + if (typeof(a) == 'function') { + if (!((d = a.apply(null, args)) && d.promise)) { + d = $.Deferred()[d === false ? 'reject' : 'resolve'](d); + } + } else if (a && a.promise) { + d = a; + } else { + d = $.Deferred()[a === false ? 'reject' : 'resolve'](a); + } + + d.fail(function() { + dfrd.reject.apply(dfrd, [].slice.apply(arguments)); + }) + .done(function(data) { + pointer++; + args.push(data); + + pointer == steps.length + ? dfrd.resolve.apply(dfrd, args) + : steps[pointer].apply(null, args); + }); + }); + }); + + steps.length ? steps[0]() : dfrd.resolve(); + + return dfrd; +} + +})(jQuery); \ No newline at end of file diff --git a/modules/backend/assets/js/winter-min.js b/modules/backend/assets/js/winter-min.js new file mode 100644 index 0000000..e8c3dbc --- /dev/null +++ b/modules/backend/assets/js/winter-min.js @@ -0,0 +1,762 @@ +(function($){$.fn.touchwipe=function(settings){var config={min_move_x:20,min_move_y:20,wipeLeft:function(){},wipeRight:function(){},wipeUp:function(){},wipeDown:function(){},preventDefaultEvents:true};if(settings)$.extend(config,settings);this.each(function(){var startX;var startY;var isMoving=false;function cancelTouch(){this.removeEventListener('touchmove',onTouchMove);startX=null;isMoving=false;}function onTouchMove(e){if(config.preventDefaultEvents){e.preventDefault();}if(isMoving){var x=e.touches[0].pageX;var y=e.touches[0].pageY;var dx=startX-x;var dy=startY-y;if(Math.abs(dx)>=config.min_move_x){cancelTouch();if(dx>0){config.wipeLeft();}else{config.wipeRight();}}else if(Math.abs(dy)>=config.min_move_y){cancelTouch();if(dy>0){config.wipeDown();}else{config.wipeUp();}}}}function onTouchStart(e){if(e.touches.length==1){startX=e.touches[0].pageX;startY=e.touches[0].pageY;isMoving=true;this.addEventListener('touchmove',onTouchMove,false);}}if('ontouchstart'in document.documentElement){ +this.addEventListener('touchstart',onTouchStart,false);}});return this;};})(jQuery);(function($){var liveUpdatingTargetSelectors={};var liveUpdaterIntervalId;var liveUpdaterRunning=false;var defaultSettings={ellipsis:'...',setTitle:'never',live:false};$.fn.ellipsis=function(selector,options){var subjectElements,settings;subjectElements=$(this);if(typeof selector!=='string'){options=selector;selector=undefined;}settings=$.extend({},defaultSettings,options);settings.selector=selector;subjectElements.each(function(){var elem=$(this);ellipsisOnElement(elem,settings);});if(settings.live){addToLiveUpdater(subjectElements.selector,settings);}else{removeFromLiveUpdater(subjectElements.selector);}return this;};function ellipsisOnElement(containerElement,settings){var containerData=containerElement.data('jqae');if(!containerData)containerData={};var wrapperElement=containerData.wrapperElement;if(!wrapperElement){wrapperElement=containerElement.wrapInner('
').find('>div');wrapperElement.css({ +margin:0,padding:0,border:0});}var wrapperElementData=wrapperElement.data('jqae');if(!wrapperElementData)wrapperElementData={};var wrapperOriginalContent=wrapperElementData.originalContent;if(wrapperOriginalContent){wrapperElement=wrapperElementData.originalContent.clone(true).data('jqae',{originalContent:wrapperOriginalContent}).replaceAll(wrapperElement);}else{wrapperElement.data('jqae',{originalContent:wrapperElement.clone(true)});}containerElement.data('jqae',{wrapperElement:wrapperElement,containerWidth:containerElement.width(),containerHeight:containerElement.height()});var containerElementHeight=containerElement.height();var wrapperOffset=(parseInt(containerElement.css('padding-top'),10)||0)+(parseInt(containerElement.css('border-top-width'),10)||0)-(wrapperElement.offset().top-containerElement.offset().top);var deferAppendEllipsis=false;var selectedElements=wrapperElement;if(settings.selector)selectedElements=$(wrapperElement.find(settings.selector).get().reverse()); +selectedElements.each(function(){var selectedElement=$(this),originalText=selectedElement.text(),ellipsisApplied=false;if(wrapperElement.innerHeight()-selectedElement.innerHeight()>containerElementHeight+wrapperOffset){selectedElement.remove();}else{removeLastEmptyElements(selectedElement);if(selectedElement.contents().length){if(deferAppendEllipsis){getLastTextNode(selectedElement).get(0).nodeValue+=settings.ellipsis;deferAppendEllipsis=false;}while(wrapperElement.innerHeight()>containerElementHeight+wrapperOffset){ellipsisApplied=ellipsisOnLastTextNode(selectedElement);if(ellipsisApplied){removeLastEmptyElements(selectedElement);if(selectedElement.contents().length){getLastTextNode(selectedElement).get(0).nodeValue+=settings.ellipsis;}else{deferAppendEllipsis=true;selectedElement.remove();break;}}else{deferAppendEllipsis=true;selectedElement.remove();break;}}if(((settings.setTitle=='onEllipsis')&&ellipsisApplied)||(settings.setTitle=='always')){selectedElement.attr('title',originalText); +}else if(settings.setTitle!='never'){selectedElement.removeAttr('title');}}}});}function ellipsisOnLastTextNode(element){var lastTextNode=getLastTextNode(element);if(lastTextNode.length){var text=lastTextNode.get(0).nodeValue;var pos=text.lastIndexOf(' ');if(pos>-1){text=$.trim(text.substring(0,pos));lastTextNode.get(0).nodeValue=text;}else{lastTextNode.get(0).nodeValue='';}return true;}return false;}function getLastTextNode(element){if(element.contents().length){var contents=element.contents();var lastNode=contents.eq(contents.length-1);if(lastNode.filter(textNodeFilter).length){return lastNode;}else{return getLastTextNode(lastNode);}}else{element.append('');var contents=element.contents();return contents.eq(contents.length-1);}}function removeLastEmptyElements(element){if(element.contents().length){var contents=element.contents();var lastNode=contents.eq(contents.length-1);if(lastNode.filter(textNodeFilter).length){var text=lastNode.get(0).nodeValue;text=$.trim(text);if(text==''){ +lastNode.remove();return true;}else{return false;}}else{while(removeLastEmptyElements(lastNode)){}if(lastNode.contents().length){return false;}else{lastNode.remove();return true;}}}return false;}function textNodeFilter(){return this.nodeType===3;}function addToLiveUpdater(targetSelector,settings){liveUpdatingTargetSelectors[targetSelector]=settings;if(!liveUpdaterIntervalId){liveUpdaterIntervalId=window.setInterval(function(){doLiveUpdater();},200);}}function removeFromLiveUpdater(targetSelector){if(liveUpdatingTargetSelectors[targetSelector]){delete liveUpdatingTargetSelectors[targetSelector];if(!liveUpdatingTargetSelectors.length){if(liveUpdaterIntervalId){window.clearInterval(liveUpdaterIntervalId);liveUpdaterIntervalId=undefined;}}}};function doLiveUpdater(){if(!liveUpdaterRunning){liveUpdaterRunning=true;for(var targetSelector in liveUpdatingTargetSelectors){$(targetSelector).each(function(){var containerElement,containerData;containerElement=$(this);containerData=containerElement.data('jqae'); +if((containerData.containerWidth!=containerElement.width())||(containerData.containerHeight!=containerElement.height())){ellipsisOnElement(containerElement,liveUpdatingTargetSelectors[targetSelector]);}});}liveUpdaterRunning=false;}};})(jQuery);(function($){$.waterfall=function(){var steps=[],dfrd=$.Deferred(),pointer=0;$.each(arguments,function(i,a){steps.push(function(){var args=[].slice.apply(arguments),d;if(typeof(a)=='function'){if(!((d=a.apply(null,args))&&d.promise)){d=$.Deferred()[d===false?'reject':'resolve'](d);}}else if(a&&a.promise){d=a;}else{d=$.Deferred()[a===false?'reject':'resolve'](a);}d.fail(function(){dfrd.reject.apply(dfrd,[].slice.apply(arguments));}).done(function(data){pointer++;args.push(data);pointer==steps.length?dfrd.resolve.apply(dfrd,args):steps[pointer].apply(null,args);});});});steps.length?steps[0]():dfrd.resolve();return dfrd;}})(jQuery);(function(factory){if(typeof define==='function'&&define.amd){define(['jquery'],factory);}else if(typeof exports==='object'){ +factory(require('jquery'));}else{factory(jQuery);}}(function($){var pluses=/\+/g;function encode(s){return config.raw?s:encodeURIComponent(s);}function decode(s){return config.raw?s:decodeURIComponent(s);}function stringifyCookieValue(value){return encode(config.json?JSON.stringify(value):String(value));}function parseCookieValue(s){if(s.indexOf('"')===0){s=s.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,'\\');}try{s=decodeURIComponent(s.replace(pluses,' '));return config.json?JSON.parse(s):s;}catch(e){}}function read(s,converter){var value=config.raw?s:parseCookieValue(s);return $.isFunction(converter)?converter(value):value;}var config=$.cookie=function(key,value,options){if(arguments.length>1&&!$.isFunction(value)){options=$.extend({},config.defaults,options);if(typeof options.expires==='number'){var days=options.expires,t=options.expires=new Date();t.setTime(+t+days*864e+5);}return(document.cookie=[encode(key),'=',stringifyCookieValue(value),options.expires?'; expires='+options.expires.toUTCString():'', +options.path?'; path='+options.path:'',options.domain?'; domain='+options.domain:'',options.secure?'; secure':''].join(''));}var result=key?undefined:{};var cookies=document.cookie?document.cookie.split('; '):[];for(var i=0,l=cookies.length;i1?_len-1:0),_key=1;_key<_len;_key++){args[_key-1]=arguments[_key];}for(var _iterator=callbacks,_isArray=true,_i=0,_iterator=_isArray?_iterator:_iterator[Symbol.iterator]();;){var _ref;if(_isArray){if(_i>=_iterator.length)break;_ref=_iterator[_i++];}else{_i=_iterator.next();if(_i.done)break;_ref=_i.value;}var callback=_ref;callback.apply(this,args);}}return this;}},{key:"off",value:function off(event,fn){if(!this._callbacks||arguments.length===0){this._callbacks={};return this;}var callbacks=this._callbacks[event];if(!callbacks){return this;}if(arguments.length===1){delete this._callbacks[event];return this;}for(var i=0;i=_iterator2.length)break;_ref2=_iterator2[_i2++];}else{_i2=_iterator2.next();if(_i2.done)break;_ref2=_i2.value;}var child=_ref2; +if(/(^| )dz-message($| )/.test(child.className)){messageElement=child;child.className="dz-message";break;}}if(!messageElement){messageElement=Dropzone.createElement("
");this.element.appendChild(messageElement);}var span=messageElement.getElementsByTagName("span")[0];if(span){if(span.textContent!=null){span.textContent=this.options.dictFallbackMessage;}else if(span.innerText!=null){span.innerText=this.options.dictFallbackMessage;}}return this.element.appendChild(this.getFallbackForm());},resize:function resize(file,width,height,resizeMethod){var info={srcX:0,srcY:0,srcWidth:file.width,srcHeight:file.height};var srcRatio=file.width/file.height;if(width==null&&height==null){width=info.srcWidth;height=info.srcHeight;}else if(width==null){width=height*srcRatio;}else if(height==null){height=width/srcRatio;}width=Math.min(width,info.srcWidth);height=Math.min(height,info.srcHeight);var trgRatio=width/height;if(info.srcWidth>width||info.srcHeight>height){ +if(resizeMethod==='crop'){if(srcRatio>trgRatio){info.srcHeight=file.height;info.srcWidth=info.srcHeight*trgRatio;}else{info.srcWidth=file.width;info.srcHeight=info.srcWidth/trgRatio;}}else if(resizeMethod==='contain'){if(srcRatio>trgRatio){height=width/srcRatio;}else{width=height*srcRatio;}}else{throw new Error("Unknown resizeMethod '"+resizeMethod+"'");}}info.srcX=(file.width-info.srcWidth)/2;info.srcY=(file.height-info.srcHeight)/2;info.trgWidth=width;info.trgHeight=height;return info;},transformFile:function transformFile(file,done){if((this.options.resizeWidth||this.options.resizeHeight)&&file.type.match(/image.*/)){return this.resizeImage(file,this.options.resizeWidth,this.options.resizeHeight,this.options.resizeMethod,done);}else{return done(file);}},previewTemplate:"
\n
\n
\n
\n
\n
\n
\n
\n
\n \n Check\n \n \n \n \n \n
\n
\n \n Error\n \n \n \n \n \n \n \n
\n
", +drop:function drop(e){return this.element.classList.remove("dz-drag-hover");},dragstart:function dragstart(e){},dragend:function dragend(e){return this.element.classList.remove("dz-drag-hover");},dragenter:function dragenter(e){return this.element.classList.add("dz-drag-hover");},dragover:function dragover(e){return this.element.classList.add("dz-drag-hover");},dragleave:function dragleave(e){return this.element.classList.remove("dz-drag-hover");},paste:function paste(e){},reset:function reset(){return this.element.classList.remove("dz-started");},addedfile:function addedfile(file){var _this2=this;if(this.element===this.previewsContainer){this.element.classList.add("dz-started");}if(this.previewsContainer){file.previewElement=Dropzone.createElement(this.options.previewTemplate.trim());file.previewTemplate=file.previewElement;this.previewsContainer.appendChild(file.previewElement);for(var _iterator3=file.previewElement.querySelectorAll("[data-dz-name]"),_isArray3=true,_i3=0,_iterator3=_isArray3?_iterator3:_iterator3[Symbol.iterator]();;){ +var _ref3;if(_isArray3){if(_i3>=_iterator3.length)break;_ref3=_iterator3[_i3++];}else{_i3=_iterator3.next();if(_i3.done)break;_ref3=_i3.value;}var node=_ref3;node.textContent=file.name;}for(var _iterator4=file.previewElement.querySelectorAll("[data-dz-size]"),_isArray4=true,_i4=0,_iterator4=_isArray4?_iterator4:_iterator4[Symbol.iterator]();;){if(_isArray4){if(_i4>=_iterator4.length)break;node=_iterator4[_i4++];}else{_i4=_iterator4.next();if(_i4.done)break;node=_i4.value;}node.innerHTML=this.filesize(file.size);}if(this.options.addRemoveLinks){file._removeLink=Dropzone.createElement(""+this.options.dictRemoveFile+"");file.previewElement.appendChild(file._removeLink);}var removeFileEvent=function removeFileEvent(e){e.preventDefault();e.stopPropagation();if(file.status===Dropzone.UPLOADING){return Dropzone.confirm(_this2.options.dictCancelUploadConfirmation,function(){return _this2.removeFile(file);});}else{if(_this2.options.dictRemoveFileConfirmation){ +return Dropzone.confirm(_this2.options.dictRemoveFileConfirmation,function(){return _this2.removeFile(file);});}else{return _this2.removeFile(file);}}};for(var _iterator5=file.previewElement.querySelectorAll("[data-dz-remove]"),_isArray5=true,_i5=0,_iterator5=_isArray5?_iterator5:_iterator5[Symbol.iterator]();;){var _ref4;if(_isArray5){if(_i5>=_iterator5.length)break;_ref4=_iterator5[_i5++];}else{_i5=_iterator5.next();if(_i5.done)break;_ref4=_i5.value;}var removeLink=_ref4;removeLink.addEventListener("click",removeFileEvent);}}},removedfile:function removedfile(file){if(file.previewElement!=null&&file.previewElement.parentNode!=null){file.previewElement.parentNode.removeChild(file.previewElement);}return this._updateMaxFilesReachedClass();},thumbnail:function thumbnail(file,dataUrl){if(file.previewElement){file.previewElement.classList.remove("dz-file-preview");for(var _iterator6=file.previewElement.querySelectorAll("[data-dz-thumbnail]"),_isArray6=true,_i6=0,_iterator6=_isArray6?_iterator6:_iterator6[Symbol.iterator]();;){ +var _ref5;if(_isArray6){if(_i6>=_iterator6.length)break;_ref5=_iterator6[_i6++];}else{_i6=_iterator6.next();if(_i6.done)break;_ref5=_i6.value;}var thumbnailElement=_ref5;thumbnailElement.alt=file.name;thumbnailElement.src=dataUrl;}return setTimeout(function(){return file.previewElement.classList.add("dz-image-preview");},1);}},error:function error(file,message){if(file.previewElement){file.previewElement.classList.add("dz-error");if(typeof message!=="String"&&message.error){message=message.error;}for(var _iterator7=file.previewElement.querySelectorAll("[data-dz-errormessage]"),_isArray7=true,_i7=0,_iterator7=_isArray7?_iterator7:_iterator7[Symbol.iterator]();;){var _ref6;if(_isArray7){if(_i7>=_iterator7.length)break;_ref6=_iterator7[_i7++];}else{_i7=_iterator7.next();if(_i7.done)break;_ref6=_i7.value;}var node=_ref6;node.textContent=message;}}},errormultiple:function errormultiple(){},processing:function processing(file){if(file.previewElement){file.previewElement.classList.add("dz-processing"); +if(file._removeLink){return file._removeLink.innerHTML=this.options.dictCancelUpload;}}},processingmultiple:function processingmultiple(){},uploadprogress:function uploadprogress(file,progress,bytesSent){if(file.previewElement){for(var _iterator8=file.previewElement.querySelectorAll("[data-dz-uploadprogress]"),_isArray8=true,_i8=0,_iterator8=_isArray8?_iterator8:_iterator8[Symbol.iterator]();;){var _ref7;if(_isArray8){if(_i8>=_iterator8.length)break;_ref7=_iterator8[_i8++];}else{_i8=_iterator8.next();if(_i8.done)break;_ref7=_i8.value;}var node=_ref7;node.nodeName==='PROGRESS'?node.value=progress:node.style.width=progress+"%";}}},totaluploadprogress:function totaluploadprogress(){},sending:function sending(){},sendingmultiple:function sendingmultiple(){},success:function success(file){if(file.previewElement){return file.previewElement.classList.add("dz-success");}},successmultiple:function successmultiple(){},canceled:function canceled(file){return this.emit("error",file,this.options.dictUploadCanceled); +},canceledmultiple:function canceledmultiple(){},complete:function complete(file){if(file._removeLink){file._removeLink.innerHTML=this.options.dictRemoveFile;}if(file.previewElement){return file.previewElement.classList.add("dz-complete");}},completemultiple:function completemultiple(){},maxfilesexceeded:function maxfilesexceeded(){},maxfilesreached:function maxfilesreached(){},queuecomplete:function queuecomplete(){},addedfiles:function addedfiles(){}};this.prototype._thumbnailQueue=[];this.prototype._processingThumbnail=false;}},{key:"extend",value:function extend(target){for(var _len2=arguments.length,objects=Array(_len2>1?_len2-1:0),_key2=1;_key2<_len2;_key2++){objects[_key2-1]=arguments[_key2];}for(var _iterator9=objects,_isArray9=true,_i9=0,_iterator9=_isArray9?_iterator9:_iterator9[Symbol.iterator]();;){var _ref8;if(_isArray9){if(_i9>=_iterator9.length)break;_ref8=_iterator9[_i9++];}else{_i9=_iterator9.next();if(_i9.done)break;_ref8=_i9.value;}var object=_ref8;for(var key in object){ +var val=object[key];target[key]=val;}}return target;}}]);function Dropzone(el,options){_classCallCheck(this,Dropzone);var _this=_possibleConstructorReturn(this,(Dropzone.__proto__||Object.getPrototypeOf(Dropzone)).call(this));var fallback=void 0,left=void 0;_this.element=el;_this.version=Dropzone.version;_this.defaultOptions.previewTemplate=_this.defaultOptions.previewTemplate.replace(/\n*/g,"");_this.clickableElements=[];_this.listeners=[];_this.files=[];if(typeof _this.element==="string"){_this.element=document.querySelector(_this.element);}if(!_this.element||_this.element.nodeType==null){throw new Error("Invalid dropzone element.");}if(_this.element.dropzone){throw new Error("Dropzone already attached.");}Dropzone.instances.push(_this);_this.element.dropzone=_this;var elementOptions=(left=Dropzone.optionsForElement(_this.element))!=null?left:{};_this.options=Dropzone.extend({},_this.defaultOptions,elementOptions,options!=null?options:{});if(_this.options.forceFallback||!Dropzone.isBrowserSupported()){ +var _ret;return _ret=_this.options.fallback.call(_this),_possibleConstructorReturn(_this,_ret);}if(_this.options.url==null){_this.options.url=_this.element.getAttribute("action");}if(!_this.options.url){throw new Error("No URL provided.");}if(_this.options.acceptedFiles&&_this.options.acceptedMimeTypes){throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");}if(_this.options.uploadMultiple&&_this.options.chunking){throw new Error('You cannot set both: uploadMultiple and chunking.');}if(_this.options.acceptedMimeTypes){_this.options.acceptedFiles=_this.options.acceptedMimeTypes;delete _this.options.acceptedMimeTypes;}if(_this.options.renameFilename!=null){_this.options.renameFile=function(file){return _this.options.renameFilename.call(_this,file.name,file);};}_this.options.method=_this.options.method.toUpperCase();if((fallback=_this.getExistingFallback())&&fallback.parentNode){fallback.parentNode.removeChild(fallback);}if(_this.options.previewsContainer!==false){ +if(_this.options.previewsContainer){_this.previewsContainer=Dropzone.getElement(_this.options.previewsContainer,"previewsContainer");}else{_this.previewsContainer=_this.element;}}if(_this.options.clickable){if(_this.options.clickable===true){_this.clickableElements=[_this.element];}else{_this.clickableElements=Dropzone.getElements(_this.options.clickable,"clickable");}}_this.init();return _this;}_createClass(Dropzone,[{key:"getAcceptedFiles",value:function getAcceptedFiles(){return this.files.filter(function(file){return file.accepted;}).map(function(file){return file;});}},{key:"getRejectedFiles",value:function getRejectedFiles(){return this.files.filter(function(file){return!file.accepted;}).map(function(file){return file;});}},{key:"getFilesWithStatus",value:function getFilesWithStatus(status){return this.files.filter(function(file){return file.status===status;}).map(function(file){return file;});}},{key:"getQueuedFiles",value:function getQueuedFiles(){return this.getFilesWithStatus(Dropzone.QUEUED); +}},{key:"getUploadingFiles",value:function getUploadingFiles(){return this.getFilesWithStatus(Dropzone.UPLOADING);}},{key:"getAddedFiles",value:function getAddedFiles(){return this.getFilesWithStatus(Dropzone.ADDED);}},{key:"getActiveFiles",value:function getActiveFiles(){return this.files.filter(function(file){return file.status===Dropzone.UPLOADING||file.status===Dropzone.QUEUED;}).map(function(file){return file;});}},{key:"init",value:function init(){var _this3=this;if(this.element.tagName==="form"){this.element.setAttribute("enctype","multipart/form-data");}if(this.element.classList.contains("dropzone")&&!this.element.querySelector(".dz-message")){this.element.appendChild(Dropzone.createElement("
"+this.options.dictDefaultMessage+"
"));}if(this.clickableElements.length){var setupHiddenFileInput=function setupHiddenFileInput(){if(_this3.hiddenFileInput){_this3.hiddenFileInput.parentNode.removeChild(_this3.hiddenFileInput);}_this3.hiddenFileInput=document.createElement("input"); +_this3.hiddenFileInput.setAttribute("type","file");if(_this3.options.maxFiles===null||_this3.options.maxFiles>1){_this3.hiddenFileInput.setAttribute("multiple","multiple");}_this3.hiddenFileInput.className="dz-hidden-input";if(_this3.options.acceptedFiles!==null){_this3.hiddenFileInput.setAttribute("accept",_this3.options.acceptedFiles);}if(_this3.options.capture!==null){_this3.hiddenFileInput.setAttribute("capture",_this3.options.capture);}_this3.hiddenFileInput.style.visibility="hidden";_this3.hiddenFileInput.style.position="absolute";_this3.hiddenFileInput.style.top="0";_this3.hiddenFileInput.style.left="0";_this3.hiddenFileInput.style.height="0";_this3.hiddenFileInput.style.width="0";Dropzone.getElement(_this3.options.hiddenInputContainer,'hiddenInputContainer').appendChild(_this3.hiddenFileInput);return _this3.hiddenFileInput.addEventListener("change",function(){var files=_this3.hiddenFileInput.files;if(files.length){for(var _iterator10=files,_isArray10=true,_i10=0,_iterator10=_isArray10?_iterator10:_iterator10[Symbol.iterator]();;){ +var _ref9;if(_isArray10){if(_i10>=_iterator10.length)break;_ref9=_iterator10[_i10++];}else{_i10=_iterator10.next();if(_i10.done)break;_ref9=_i10.value;}var file=_ref9;_this3.addFile(file);}}_this3.emit("addedfiles",files);return setupHiddenFileInput();});};setupHiddenFileInput();}this.URL=window.URL!==null?window.URL:window.webkitURL;for(var _iterator11=this.events,_isArray11=true,_i11=0,_iterator11=_isArray11?_iterator11:_iterator11[Symbol.iterator]();;){var _ref10;if(_isArray11){if(_i11>=_iterator11.length)break;_ref10=_iterator11[_i11++];}else{_i11=_iterator11.next();if(_i11.done)break;_ref10=_i11.value;}var eventName=_ref10;this.on(eventName,this.options[eventName]);}this.on("uploadprogress",function(){return _this3.updateTotalUploadProgress();});this.on("removedfile",function(){return _this3.updateTotalUploadProgress();});this.on("canceled",function(file){return _this3.emit("complete",file);});this.on("complete",function(file){if(_this3.getAddedFiles().length===0&&_this3.getUploadingFiles().length===0&&_this3.getQueuedFiles().length===0){ +return setTimeout(function(){return _this3.emit("queuecomplete");},0);}});var noPropagation=function noPropagation(e){e.stopPropagation();if(e.preventDefault){return e.preventDefault();}else{return e.returnValue=false;}};this.listeners=[{element:this.element,events:{"dragstart":function dragstart(e){return _this3.emit("dragstart",e);},"dragenter":function dragenter(e){noPropagation(e);return _this3.emit("dragenter",e);},"dragover":function dragover(e){var efct=void 0;try{efct=e.dataTransfer.effectAllowed;}catch(error){}e.dataTransfer.dropEffect='move'===efct||'linkMove'===efct?'move':'copy';noPropagation(e);return _this3.emit("dragover",e);},"dragleave":function dragleave(e){return _this3.emit("dragleave",e);},"drop":function drop(e){noPropagation(e);return _this3.drop(e);},"dragend":function dragend(e){return _this3.emit("dragend",e);}}}];this.clickableElements.forEach(function(clickableElement){return _this3.listeners.push({element:clickableElement,events:{"click":function click(evt){ +if(clickableElement!==_this3.element||evt.target===_this3.element||Dropzone.elementInside(evt.target,_this3.element.querySelector(".dz-message"))){_this3.hiddenFileInput.click();}return true;}}});});this.enable();return this.options.init.call(this);}},{key:"destroy",value:function destroy(){this.disable();this.removeAllFiles(true);if(this.hiddenFileInput!=null?this.hiddenFileInput.parentNode:undefined){this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);this.hiddenFileInput=null;}delete this.element.dropzone;return Dropzone.instances.splice(Dropzone.instances.indexOf(this),1);}},{key:"updateTotalUploadProgress",value:function updateTotalUploadProgress(){var totalUploadProgress=void 0;var totalBytesSent=0;var totalBytes=0;var activeFiles=this.getActiveFiles();if(activeFiles.length){for(var _iterator12=this.getActiveFiles(),_isArray12=true,_i12=0,_iterator12=_isArray12?_iterator12:_iterator12[Symbol.iterator]();;){var _ref11;if(_isArray12){if(_i12>=_iterator12.length)break; +_ref11=_iterator12[_i12++];}else{_i12=_iterator12.next();if(_i12.done)break;_ref11=_i12.value;}var file=_ref11;totalBytesSent+=file.upload.bytesSent;totalBytes+=file.upload.total;}totalUploadProgress=100*totalBytesSent/totalBytes;}else{totalUploadProgress=100;}return this.emit("totaluploadprogress",totalUploadProgress,totalBytes,totalBytesSent);}},{key:"_getParamName",value:function _getParamName(n){if(typeof this.options.paramName==="function"){return this.options.paramName(n);}else{return""+this.options.paramName+(this.options.uploadMultiple?"["+n+"]":"");}}},{key:"_renameFile",value:function _renameFile(file){if(typeof this.options.renameFile!=="function"){return file.name;}return this.options.renameFile(file);}},{key:"getFallbackForm",value:function getFallbackForm(){var existingFallback=void 0,form=void 0;if(existingFallback=this.getExistingFallback()){return existingFallback;}var fieldsString="
";if(this.options.dictFallbackText){fieldsString+="

"+this.options.dictFallbackText+"

"; +}fieldsString+="
";var fields=Dropzone.createElement(fieldsString);if(this.element.tagName!=="FORM"){form=Dropzone.createElement("
");form.appendChild(fields);}else{this.element.setAttribute("enctype","multipart/form-data");this.element.setAttribute("method",this.options.method);}return form!=null?form:fields;}},{key:"getExistingFallback",value:function getExistingFallback(){var getFallback=function getFallback(elements){for(var _iterator13=elements,_isArray13=true,_i13=0,_iterator13=_isArray13?_iterator13:_iterator13[Symbol.iterator]();;){var _ref12;if(_isArray13){if(_i13>=_iterator13.length)break;_ref12=_iterator13[_i13++];}else{_i13=_iterator13.next();if(_i13.done)break;_ref12=_i13.value;}var el=_ref12;if(/(^| )fallback($| )/.test(el.className)){ +return el;}}};var _arr=["div","form"];for(var _i14=0;_i14<_arr.length;_i14++){var tagName=_arr[_i14];var fallback;if(fallback=getFallback(this.element.getElementsByTagName(tagName))){return fallback;}}}},{key:"setupEventListeners",value:function setupEventListeners(){return this.listeners.map(function(elementListeners){return function(){var result=[];for(var event in elementListeners.events){var listener=elementListeners.events[event];result.push(elementListeners.element.addEventListener(event,listener,false));}return result;}();});}},{key:"removeEventListeners",value:function removeEventListeners(){return this.listeners.map(function(elementListeners){return function(){var result=[];for(var event in elementListeners.events){var listener=elementListeners.events[event];result.push(elementListeners.element.removeEventListener(event,listener,false));}return result;}();});}},{key:"disable",value:function disable(){var _this4=this;this.clickableElements.forEach(function(element){return element.classList.remove("dz-clickable"); +});this.removeEventListeners();this.disabled=true;return this.files.map(function(file){return _this4.cancelUpload(file);});}},{key:"enable",value:function enable(){delete this.disabled;this.clickableElements.forEach(function(element){return element.classList.add("dz-clickable");});return this.setupEventListeners();}},{key:"filesize",value:function filesize(size){var selectedSize=0;var selectedUnit="b";if(size>0){var units=['tb','gb','mb','kb','b'];for(var i=0;i=cutoff){selectedSize=size/Math.pow(this.options.filesizeBase,4-i);selectedUnit=unit;break;}}selectedSize=Math.round(10*selectedSize)/10;}return""+selectedSize+" "+this.options.dictFileSizeUnits[selectedUnit];}},{key:"_updateMaxFilesReachedClass",value:function _updateMaxFilesReachedClass(){if(this.options.maxFiles!=null&&this.getAcceptedFiles().length>=this.options.maxFiles){if(this.getAcceptedFiles().length===this.options.maxFiles){ +this.emit('maxfilesreached',this.files);}return this.element.classList.add("dz-max-files-reached");}else{return this.element.classList.remove("dz-max-files-reached");}}},{key:"drop",value:function drop(e){if(!e.dataTransfer){return;}this.emit("drop",e);var files=[];for(var i=0;i=_iterator14.length)break; +_ref13=_iterator14[_i15++];}else{_i15=_iterator14.next();if(_i15.done)break;_ref13=_i15.value;}var file=_ref13;this.addFile(file);}}},{key:"_addFilesFromItems",value:function _addFilesFromItems(items){var _this5=this;return function(){var result=[];for(var _iterator15=items,_isArray15=true,_i16=0,_iterator15=_isArray15?_iterator15:_iterator15[Symbol.iterator]();;){var _ref14;if(_isArray15){if(_i16>=_iterator15.length)break;_ref14=_iterator15[_i16++];}else{_i16=_iterator15.next();if(_i16.done)break;_ref14=_i16.value;}var item=_ref14;var entry;if(item.webkitGetAsEntry!=null&&(entry=item.webkitGetAsEntry())){if(entry.isFile){result.push(_this5.addFile(item.getAsFile()));}else if(entry.isDirectory){result.push(_this5._addFilesFromDirectory(entry,entry.name));}else{result.push(undefined);}}else if(item.getAsFile!=null){if(item.kind==null||item.kind==="file"){result.push(_this5.addFile(item.getAsFile()));}else{result.push(undefined);}}else{result.push(undefined);}}return result;}();}},{key:"_addFilesFromDirectory", +value:function _addFilesFromDirectory(directory,path){var _this6=this;var dirReader=directory.createReader();var errorHandler=function errorHandler(error){return __guardMethod__(console,'log',function(o){return o.log(error);});};var readEntries=function readEntries(){return dirReader.readEntries(function(entries){if(entries.length>0){for(var _iterator16=entries,_isArray16=true,_i17=0,_iterator16=_isArray16?_iterator16:_iterator16[Symbol.iterator]();;){var _ref15;if(_isArray16){if(_i17>=_iterator16.length)break;_ref15=_iterator16[_i17++];}else{_i17=_iterator16.next();if(_i17.done)break;_ref15=_i17.value;}var entry=_ref15;if(entry.isFile){entry.file(function(file){if(_this6.options.ignoreHiddenFiles&&file.name.substring(0,1)==='.'){return;}file.fullPath=path+"/"+file.name;return _this6.addFile(file);});}else if(entry.isDirectory){_this6._addFilesFromDirectory(entry,path+"/"+entry.name);}}readEntries();}return null;},errorHandler);};return readEntries();}},{key:"accept",value:function accept(file,done){ +if(this.options.maxFilesize&&file.size>this.options.maxFilesize*1024*1024){return done(this.options.dictFileTooBig.replace("{{filesize}}",Math.round(file.size/1024/10.24)/100).replace("{{maxFilesize}}",this.options.maxFilesize));}else if(!Dropzone.isValidFile(file,this.options.acceptedFiles)){return done(this.options.dictInvalidFileType);}else if(this.options.maxFiles!=null&&this.getAcceptedFiles().length>=this.options.maxFiles){done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}",this.options.maxFiles));return this.emit("maxfilesexceeded",file);}else{return this.options.accept.call(this,file,done);}}},{key:"addFile",value:function addFile(file){var _this7=this;file.upload={uuid:Dropzone.uuidv4(),progress:0,total:file.size,bytesSent:0,filename:this._renameFile(file),chunked:this.options.chunking&&(this.options.forceChunking||file.size>this.options.chunkSize),totalChunkCount:Math.ceil(file.size/this.options.chunkSize)};this.files.push(file);file.status=Dropzone.ADDED;this.emit("addedfile",file); +this._enqueueThumbnail(file);return this.accept(file,function(error){if(error){file.accepted=false;_this7._errorProcessing([file],error);}else{file.accepted=true;if(_this7.options.autoQueue){_this7.enqueueFile(file);}}return _this7._updateMaxFilesReachedClass();});}},{key:"enqueueFiles",value:function enqueueFiles(files){for(var _iterator17=files,_isArray17=true,_i18=0,_iterator17=_isArray17?_iterator17:_iterator17[Symbol.iterator]();;){var _ref16;if(_isArray17){if(_i18>=_iterator17.length)break;_ref16=_iterator17[_i18++];}else{_i18=_iterator17.next();if(_i18.done)break;_ref16=_i18.value;}var file=_ref16;this.enqueueFile(file);}return null;}},{key:"enqueueFile",value:function enqueueFile(file){var _this8=this;if(file.status===Dropzone.ADDED&&file.accepted===true){file.status=Dropzone.QUEUED;if(this.options.autoProcessQueue){return setTimeout(function(){return _this8.processQueue();},0);}}else{throw new Error("This file can't be queued because it has already been processed or was rejected."); +}}},{key:"_enqueueThumbnail",value:function _enqueueThumbnail(file){var _this9=this;if(this.options.createImageThumbnails&&file.type.match(/image.*/)&&file.size<=this.options.maxThumbnailFilesize*1024*1024){this._thumbnailQueue.push(file);return setTimeout(function(){return _this9._processThumbnailQueue();},0);}}},{key:"_processThumbnailQueue",value:function _processThumbnailQueue(){var _this10=this;if(this._processingThumbnail||this._thumbnailQueue.length===0){return;}this._processingThumbnail=true;var file=this._thumbnailQueue.shift();return this.createThumbnail(file,this.options.thumbnailWidth,this.options.thumbnailHeight,this.options.thumbnailMethod,true,function(dataUrl){_this10.emit("thumbnail",file,dataUrl);_this10._processingThumbnail=false;return _this10._processThumbnailQueue();});}},{key:"removeFile",value:function removeFile(file){if(file.status===Dropzone.UPLOADING){this.cancelUpload(file);}this.files=without(this.files,file);this.emit("removedfile",file);if(this.files.length===0){ +return this.emit("reset");}}},{key:"removeAllFiles",value:function removeAllFiles(cancelIfNecessary){if(cancelIfNecessary==null){cancelIfNecessary=false;}for(var _iterator18=this.files.slice(),_isArray18=true,_i19=0,_iterator18=_isArray18?_iterator18:_iterator18[Symbol.iterator]();;){var _ref17;if(_isArray18){if(_i19>=_iterator18.length)break;_ref17=_iterator18[_i19++];}else{_i19=_iterator18.next();if(_i19.done)break;_ref17=_i19.value;}var file=_ref17;if(file.status!==Dropzone.UPLOADING||cancelIfNecessary){this.removeFile(file);}}return null;}},{key:"resizeImage",value:function resizeImage(file,width,height,resizeMethod,callback){var _this11=this;return this.createThumbnail(file,width,height,resizeMethod,true,function(dataUrl,canvas){if(canvas==null){return callback(file);}else{var resizeMimeType=_this11.options.resizeMimeType;if(resizeMimeType==null){resizeMimeType=file.type;}var resizedDataURL=canvas.toDataURL(resizeMimeType,_this11.options.resizeQuality);if(resizeMimeType==='image/jpeg'||resizeMimeType==='image/jpg'){ +resizedDataURL=ExifRestore.restore(file.dataURL,resizedDataURL);}return callback(Dropzone.dataURItoBlob(resizedDataURL));}});}},{key:"createThumbnail",value:function createThumbnail(file,width,height,resizeMethod,fixOrientation,callback){var _this12=this;var fileReader=new FileReader();fileReader.onload=function(){file.dataURL=fileReader.result;if(file.type==="image/svg+xml"){if(callback!=null){callback(fileReader.result);}return;}return _this12.createThumbnailFromUrl(file,width,height,resizeMethod,fixOrientation,callback);};return fileReader.readAsDataURL(file);}},{key:"createThumbnailFromUrl",value:function createThumbnailFromUrl(file,width,height,resizeMethod,fixOrientation,callback,crossOrigin){var _this13=this;var img=document.createElement("img");if(crossOrigin){img.crossOrigin=crossOrigin;}img.onload=function(){var loadExif=function loadExif(callback){return callback(1);};if(typeof EXIF!=='undefined'&&EXIF!==null&&fixOrientation){loadExif=function loadExif(callback){return EXIF.getData(img,function(){ +return callback(EXIF.getTag(this,'Orientation'));});};}return loadExif(function(orientation){file.width=img.width;file.height=img.height;var resizeInfo=_this13.options.resize.call(_this13,file,width,height,resizeMethod);var canvas=document.createElement("canvas");var ctx=canvas.getContext("2d");canvas.width=resizeInfo.trgWidth;canvas.height=resizeInfo.trgHeight;if(orientation>4){canvas.width=resizeInfo.trgHeight;canvas.height=resizeInfo.trgWidth;}switch(orientation){case 2:ctx.translate(canvas.width,0);ctx.scale(-1,1);break;case 3:ctx.translate(canvas.width,canvas.height);ctx.rotate(Math.PI);break;case 4:ctx.translate(0,canvas.height);ctx.scale(1,-1);break;case 5:ctx.rotate(0.5*Math.PI);ctx.scale(1,-1);break;case 6:ctx.rotate(0.5*Math.PI);ctx.translate(0,-canvas.width);break;case 7:ctx.rotate(0.5*Math.PI);ctx.translate(canvas.height,-canvas.width);ctx.scale(-1,1);break;case 8:ctx.rotate(-0.5*Math.PI);ctx.translate(-canvas.height,0);break;}drawImageIOSFix(ctx,img,resizeInfo.srcX!=null?resizeInfo.srcX:0,resizeInfo.srcY!=null?resizeInfo.srcY:0,resizeInfo.srcWidth,resizeInfo.srcHeight,resizeInfo.trgX!=null?resizeInfo.trgX:0,resizeInfo.trgY!=null?resizeInfo.trgY:0,resizeInfo.trgWidth,resizeInfo.trgHeight); +var thumbnail=canvas.toDataURL("image/png");if(callback!=null){return callback(thumbnail,canvas);}});};if(callback!=null){img.onerror=callback;}return img.src=file.dataURL;}},{key:"processQueue",value:function processQueue(){var parallelUploads=this.options.parallelUploads;var processingLength=this.getUploadingFiles().length;var i=processingLength;if(processingLength>=parallelUploads){return;}var queuedFiles=this.getQueuedFiles();if(!(queuedFiles.length>0)){return;}if(this.options.uploadMultiple){return this.processFiles(queuedFiles.slice(0,parallelUploads-processingLength));}else{while(i=_iterator19.length)break; +_ref18=_iterator19[_i20++];}else{_i20=_iterator19.next();if(_i20.done)break;_ref18=_i20.value;}var file=_ref18;file.processing=true;file.status=Dropzone.UPLOADING;this.emit("processing",file);}if(this.options.uploadMultiple){this.emit("processingmultiple",files);}return this.uploadFiles(files);}},{key:"_getFilesWithXhr",value:function _getFilesWithXhr(xhr){var files=void 0;return files=this.files.filter(function(file){return file.xhr===xhr;}).map(function(file){return file;});}},{key:"cancelUpload",value:function cancelUpload(file){if(file.status===Dropzone.UPLOADING){var groupedFiles=this._getFilesWithXhr(file.xhr);for(var _iterator20=groupedFiles,_isArray20=true,_i21=0,_iterator20=_isArray20?_iterator20:_iterator20[Symbol.iterator]();;){var _ref19;if(_isArray20){if(_i21>=_iterator20.length)break;_ref19=_iterator20[_i21++];}else{_i21=_iterator20.next();if(_i21.done)break;_ref19=_i21.value;}var groupedFile=_ref19;groupedFile.status=Dropzone.CANCELED;}if(typeof file.xhr!=='undefined'){ +file.xhr.abort();}for(var _iterator21=groupedFiles,_isArray21=true,_i22=0,_iterator21=_isArray21?_iterator21:_iterator21[Symbol.iterator]();;){var _ref20;if(_isArray21){if(_i22>=_iterator21.length)break;_ref20=_iterator21[_i22++];}else{_i22=_iterator21.next();if(_i22.done)break;_ref20=_i22.value;}var _groupedFile=_ref20;this.emit("canceled",_groupedFile);}if(this.options.uploadMultiple){this.emit("canceledmultiple",groupedFiles);}}else if(file.status===Dropzone.ADDED||file.status===Dropzone.QUEUED){file.status=Dropzone.CANCELED;this.emit("canceled",file);if(this.options.uploadMultiple){this.emit("canceledmultiple",[file]);}}if(this.options.autoProcessQueue){return this.processQueue();}}},{key:"resolveOption",value:function resolveOption(option){if(typeof option==='function'){for(var _len3=arguments.length,args=Array(_len3>1?_len3-1:0),_key3=1;_key3<_len3;_key3++){args[_key3-1]=arguments[_key3];}return option.apply(this,args);}return option;}},{key:"uploadFile",value:function uploadFile(file){ +return this.uploadFiles([file]);}},{key:"uploadFiles",value:function uploadFiles(files){var _this14=this;this._transformFiles(files,function(transformedFiles){if(files[0].upload.chunked){var file=files[0];var transformedFile=transformedFiles[0];var startedChunkCount=0;file.upload.chunks=[];var handleNextChunk=function handleNextChunk(){var chunkIndex=0;while(file.upload.chunks[chunkIndex]!==undefined){chunkIndex++;}if(chunkIndex>=file.upload.totalChunkCount)return;startedChunkCount++;var start=chunkIndex*_this14.options.chunkSize;var end=Math.min(start+_this14.options.chunkSize,file.size);var dataBlock={name:_this14._getParamName(0),data:transformedFile.webkitSlice?transformedFile.webkitSlice(start,end):transformedFile.slice(start,end),filename:file.upload.filename,chunkIndex:chunkIndex};file.upload.chunks[chunkIndex]={file:file,index:chunkIndex,dataBlock:dataBlock,status:Dropzone.UPLOADING,progress:0,retries:0};_this14._uploadData(files,[dataBlock]);};file.upload.finishedChunkUpload=function(chunk){ +var allFinished=true;chunk.status=Dropzone.SUCCESS;chunk.dataBlock=null;chunk.xhr=null;for(var i=0;i=_iterator22.length)break;_ref21=_iterator22[_i24++];}else{_i24=_iterator22.next();if(_i24.done)break;_ref21=_i24.value;}var file=_ref21;file.xhr=xhr;}if(files[0].upload.chunked){files[0].upload.chunks[dataBlocks[0].chunkIndex].xhr=xhr;}var method=this.resolveOption(this.options.method,files);var url=this.resolveOption(this.options.url,files);xhr.open(method,url,true);xhr.timeout=this.resolveOption(this.options.timeout,files);xhr.withCredentials=!!this.options.withCredentials;xhr.onload=function(e){_this15._finishedUploading(files,xhr,e);};xhr.onerror=function(){_this15._handleUploadError(files,xhr);};var progressObj=xhr.upload!=null?xhr.upload:xhr;progressObj.onprogress=function(e){return _this15._updateFilesUploadProgress(files,xhr,e);};var headers={"Accept":"application/json", +"Cache-Control":"no-cache","X-Requested-With":"XMLHttpRequest"};if(this.options.headers){Dropzone.extend(headers,this.options.headers);}for(var headerName in headers){var headerValue=headers[headerName];if(headerValue){xhr.setRequestHeader(headerName,headerValue);}}var formData=new FormData();if(this.options.params){var additionalParams=this.options.params;if(typeof additionalParams==='function'){additionalParams=additionalParams.call(this,files,xhr,files[0].upload.chunked?this._getChunk(files[0],xhr):null);}for(var key in additionalParams){var value=additionalParams[key];formData.append(key,value);}}for(var _iterator23=files,_isArray23=true,_i25=0,_iterator23=_isArray23?_iterator23:_iterator23[Symbol.iterator]();;){var _ref22;if(_isArray23){if(_i25>=_iterator23.length)break;_ref22=_iterator23[_i25++];}else{_i25=_iterator23.next();if(_i25.done)break;_ref22=_i25.value;}var _file=_ref22;this.emit("sending",_file,xhr,formData);}if(this.options.uploadMultiple){this.emit("sendingmultiple",files,xhr,formData); +}this._addFormElementData(formData);for(var i=0;i=_iterator24.length)break;_ref23=_iterator24[_i26++];}else{_i26=_iterator24.next();if(_i26.done)break; +_ref23=_i26.value;}var input=_ref23;var inputName=input.getAttribute("name");var inputType=input.getAttribute("type");if(inputType)inputType=inputType.toLowerCase();if(typeof inputName==='undefined'||inputName===null)continue;if(input.tagName==="SELECT"&&input.hasAttribute("multiple")){for(var _iterator25=input.options,_isArray25=true,_i27=0,_iterator25=_isArray25?_iterator25:_iterator25[Symbol.iterator]();;){var _ref24;if(_isArray25){if(_i27>=_iterator25.length)break;_ref24=_iterator25[_i27++];}else{_i27=_iterator25.next();if(_i27.done)break;_ref24=_i27.value;}var option=_ref24;if(option.selected){formData.append(inputName,option.value);}}}else if(!inputType||inputType!=="checkbox"&&inputType!=="radio"||input.checked){formData.append(inputName,input.value);}}}}},{key:"_updateFilesUploadProgress",value:function _updateFilesUploadProgress(files,xhr,e){var progress=void 0;if(typeof e!=='undefined'){progress=100*e.loaded/e.total;if(files[0].upload.chunked){var file=files[0];var chunk=this._getChunk(file,xhr); +chunk.progress=progress;chunk.total=e.total;chunk.bytesSent=e.loaded;var fileProgress=0,fileTotal=void 0,fileBytesSent=void 0;file.upload.progress=0;file.upload.total=0;file.upload.bytesSent=0;for(var i=0;i=_iterator26.length)break;_ref25=_iterator26[_i28++];}else{_i28=_iterator26.next();if(_i28.done)break;_ref25=_i28.value;}var _file2=_ref25;_file2.upload.progress=progress;_file2.upload.total=e.total;_file2.upload.bytesSent=e.loaded;}}for(var _iterator27=files,_isArray27=true,_i29=0,_iterator27=_isArray27?_iterator27:_iterator27[Symbol.iterator]();;){ +var _ref26;if(_isArray27){if(_i29>=_iterator27.length)break;_ref26=_iterator27[_i29++];}else{_i29=_iterator27.next();if(_i29.done)break;_ref26=_i29.value;}var _file3=_ref26;this.emit("uploadprogress",_file3,_file3.upload.progress,_file3.upload.bytesSent);}}else{var allFilesFinished=true;progress=100;for(var _iterator28=files,_isArray28=true,_i30=0,_iterator28=_isArray28?_iterator28:_iterator28[Symbol.iterator]();;){var _ref27;if(_isArray28){if(_i30>=_iterator28.length)break;_ref27=_iterator28[_i30++];}else{_i30=_iterator28.next();if(_i30.done)break;_ref27=_i30.value;}var _file4=_ref27;if(_file4.upload.progress!==100||_file4.upload.bytesSent!==_file4.upload.total){allFilesFinished=false;}_file4.upload.progress=progress;_file4.upload.bytesSent=_file4.upload.total;}if(allFilesFinished){return;}for(var _iterator29=files,_isArray29=true,_i31=0,_iterator29=_isArray29?_iterator29:_iterator29[Symbol.iterator]();;){var _ref28;if(_isArray29){if(_i31>=_iterator29.length)break;_ref28=_iterator29[_i31++]; +}else{_i31=_iterator29.next();if(_i31.done)break;_ref28=_i31.value;}var _file5=_ref28;this.emit("uploadprogress",_file5,progress,_file5.upload.bytesSent);}}}},{key:"_finishedUploading",value:function _finishedUploading(files,xhr,e){var response=void 0;if(files[0].status===Dropzone.CANCELED){return;}if(xhr.readyState!==4){return;}if(xhr.responseType!=='arraybuffer'&&xhr.responseType!=='blob'){response=xhr.responseText;if(xhr.getResponseHeader("content-type")&&~xhr.getResponseHeader("content-type").indexOf("application/json")){try{response=JSON.parse(response);}catch(error){e=error;response="Invalid JSON response from server.";}}}this._updateFilesUploadProgress(files);if(!(200<=xhr.status&&xhr.status<300)){this._handleUploadError(files,xhr,response);}else{if(files[0].upload.chunked){files[0].upload.finishedChunkUpload(this._getChunk(files[0],xhr));}else{this._finished(files,response,e);}}}},{key:"_handleUploadError",value:function _handleUploadError(files,xhr,response){if(files[0].status===Dropzone.CANCELED){ +return;}if(files[0].upload.chunked&&this.options.retryChunks){var chunk=this._getChunk(files[0],xhr);if(chunk.retries++=_iterator30.length)break;_ref29=_iterator30[_i32++];}else{_i32=_iterator30.next();if(_i32.done)break;_ref29=_i32.value;}var file=_ref29;this._errorProcessing(files,response||this.options.dictResponseError.replace("{{statusCode}}",xhr.status),xhr);}}},{key:"submitRequest",value:function submitRequest(xhr,formData,files){xhr.send(formData);}},{key:"_finished",value:function _finished(files,responseText,e){for(var _iterator31=files,_isArray31=true,_i33=0,_iterator31=_isArray31?_iterator31:_iterator31[Symbol.iterator]();;){var _ref30;if(_isArray31){if(_i33>=_iterator31.length)break; +_ref30=_iterator31[_i33++];}else{_i33=_iterator31.next();if(_i33.done)break;_ref30=_i33.value;}var file=_ref30;file.status=Dropzone.SUCCESS;this.emit("success",file,responseText,e);this.emit("complete",file);}if(this.options.uploadMultiple){this.emit("successmultiple",files,responseText,e);this.emit("completemultiple",files);}if(this.options.autoProcessQueue){return this.processQueue();}}},{key:"_errorProcessing",value:function _errorProcessing(files,message,xhr){for(var _iterator32=files,_isArray32=true,_i34=0,_iterator32=_isArray32?_iterator32:_iterator32[Symbol.iterator]();;){var _ref31;if(_isArray32){if(_i34>=_iterator32.length)break;_ref31=_iterator32[_i34++];}else{_i34=_iterator32.next();if(_i34.done)break;_ref31=_i34.value;}var file=_ref31;file.status=Dropzone.ERROR;this.emit("error",file,message,xhr);this.emit("complete",file);}if(this.options.uploadMultiple){this.emit("errormultiple",files,message,xhr);this.emit("completemultiple",files);}if(this.options.autoProcessQueue){ +return this.processQueue();}}}],[{key:"uuidv4",value:function uuidv4(){return'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(c){var r=Math.random()*16|0,v=c==='x'?r:r&0x3|0x8;return v.toString(16);});}}]);return Dropzone;}(Emitter);Dropzone.initClass();Dropzone.version="5.5.1";Dropzone.options={};Dropzone.optionsForElement=function(element){if(element.getAttribute("id")){return Dropzone.options[camelize(element.getAttribute("id"))];}else{return undefined;}};Dropzone.instances=[];Dropzone.forElement=function(element){if(typeof element==="string"){element=document.querySelector(element);}if((element!=null?element.dropzone:undefined)==null){throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.");}return element.dropzone;};Dropzone.autoDiscover=true;Dropzone.discover=function(){var dropzones=void 0;if(document.querySelectorAll){ +dropzones=document.querySelectorAll(".dropzone");}else{dropzones=[];var checkElements=function checkElements(elements){return function(){var result=[];for(var _iterator33=elements,_isArray33=true,_i35=0,_iterator33=_isArray33?_iterator33:_iterator33[Symbol.iterator]();;){var _ref32;if(_isArray33){if(_i35>=_iterator33.length)break;_ref32=_iterator33[_i35++];}else{_i35=_iterator33.next();if(_i35.done)break;_ref32=_i35.value;}var el=_ref32;if(/(^| )dropzone($| )/.test(el.className)){result.push(dropzones.push(el));}else{result.push(undefined);}}return result;}();};checkElements(document.getElementsByTagName("div"));checkElements(document.getElementsByTagName("form"));}return function(){var result=[];for(var _iterator34=dropzones,_isArray34=true,_i36=0,_iterator34=_isArray34?_iterator34:_iterator34[Symbol.iterator]();;){var _ref33;if(_isArray34){if(_i36>=_iterator34.length)break;_ref33=_iterator34[_i36++];}else{_i36=_iterator34.next();if(_i36.done)break;_ref33=_i36.value;}var dropzone=_ref33; +if(Dropzone.optionsForElement(dropzone)!==false){result.push(new Dropzone(dropzone));}else{result.push(undefined);}}return result;}();};Dropzone.blacklistedBrowsers=[/opera.*(Macintosh|Windows Phone).*version\/12/i];Dropzone.isBrowserSupported=function(){var capableBrowser=true;if(window.File&&window.FileReader&&window.FileList&&window.Blob&&window.FormData&&document.querySelector){if(!("classList"in document.createElement("a"))){capableBrowser=false;}else{for(var _iterator35=Dropzone.blacklistedBrowsers,_isArray35=true,_i37=0,_iterator35=_isArray35?_iterator35:_iterator35[Symbol.iterator]();;){var _ref34;if(_isArray35){if(_i37>=_iterator35.length)break;_ref34=_iterator35[_i37++];}else{_i37=_iterator35.next();if(_i37.done)break;_ref34=_i37.value;}var regex=_ref34;if(regex.test(navigator.userAgent)){capableBrowser=false;continue;}}}}else{capableBrowser=false;}return capableBrowser;};Dropzone.dataURItoBlob=function(dataURI){var byteString=atob(dataURI.split(',')[1]);var mimeString=dataURI.split(',')[0].split(':')[1].split(';')[0]; +var ab=new ArrayBuffer(byteString.length);var ia=new Uint8Array(ab);for(var i=0,end=byteString.length,asc=0<=end;asc?i<=end:i>=end;asc?i++:i--){ia[i]=byteString.charCodeAt(i);}return new Blob([ab],{type:mimeString});};var without=function without(list,rejectedItem){return list.filter(function(item){return item!==rejectedItem;}).map(function(item){return item;});};var camelize=function camelize(str){return str.replace(/[\-_](\w)/g,function(match){return match.charAt(1).toUpperCase();});};Dropzone.createElement=function(string){var div=document.createElement("div");div.innerHTML=string;return div.childNodes[0];};Dropzone.elementInside=function(element,container){if(element===container){return true;}while(element=element.parentNode){if(element===container){return true;}}return false;};Dropzone.getElement=function(el,name){var element=void 0;if(typeof el==="string"){element=document.querySelector(el);}else if(el.nodeType!=null){element=el;}if(element==null){throw new Error("Invalid `"+name+"` option provided. Please provide a CSS selector or a plain HTML element."); +}return element;};Dropzone.getElements=function(els,name){var el=void 0,elements=void 0;if(els instanceof Array){elements=[];try{for(var _iterator36=els,_isArray36=true,_i38=0,_iterator36=_isArray36?_iterator36:_iterator36[Symbol.iterator]();;){if(_isArray36){if(_i38>=_iterator36.length)break;el=_iterator36[_i38++];}else{_i38=_iterator36.next();if(_i38.done)break;el=_i38.value;}elements.push(this.getElement(el,name));}}catch(e){elements=null;}}else if(typeof els==="string"){elements=[];for(var _iterator37=document.querySelectorAll(els),_isArray37=true,_i39=0,_iterator37=_isArray37?_iterator37:_iterator37[Symbol.iterator]();;){if(_isArray37){if(_i39>=_iterator37.length)break;el=_iterator37[_i39++];}else{_i39=_iterator37.next();if(_i39.done)break;el=_i39.value;}elements.push(el);}}else if(els.nodeType!=null){elements=[els];}if(elements==null||!elements.length){throw new Error("Invalid `"+name+"` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");} +return elements;};Dropzone.confirm=function(question,accepted,rejected){if(window.confirm(question)){return accepted();}else if(rejected!=null){return rejected();}};Dropzone.isValidFile=function(file,acceptedFiles){if(!acceptedFiles){return true;}acceptedFiles=acceptedFiles.split(",");var mimeType=file.type;var baseMimeType=mimeType.replace(/\/.*$/,"");for(var _iterator38=acceptedFiles,_isArray38=true,_i40=0,_iterator38=_isArray38?_iterator38:_iterator38[Symbol.iterator]();;){var _ref35;if(_isArray38){if(_i40>=_iterator38.length)break;_ref35=_iterator38[_i40++];}else{_i40=_iterator38.next();if(_i40.done)break;_ref35=_i40.value;}var validType=_ref35;validType=validType.trim();if(validType.charAt(0)==="."){if(file.name.toLowerCase().indexOf(validType.toLowerCase(),file.name.length-validType.length)!==-1){return true;}}else if(/\/\*$/.test(validType)){if(baseMimeType===validType.replace(/\/.*$/,"")){return true;}}else{if(mimeType===validType){return true;}}}return false;};if(typeof jQuery!=='undefined'&&jQuery!==null){ +jQuery.fn.dropzone=function(options){return this.each(function(){return new Dropzone(this,options);});};}if(typeof module!=='undefined'&&module!==null){module.exports=Dropzone;}else{window.Dropzone=Dropzone;}Dropzone.ADDED="added";Dropzone.QUEUED="queued";Dropzone.ACCEPTED=Dropzone.QUEUED;Dropzone.UPLOADING="uploading";Dropzone.PROCESSING=Dropzone.UPLOADING;Dropzone.CANCELED="canceled";Dropzone.ERROR="error";Dropzone.SUCCESS="success";var detectVerticalSquash=function detectVerticalSquash(img){var iw=img.naturalWidth;var ih=img.naturalHeight;var canvas=document.createElement("canvas");canvas.width=1;canvas.height=ih;var ctx=canvas.getContext("2d");ctx.drawImage(img,0,0);var _ctx$getImageData=ctx.getImageData(1,0,1,ih),data=_ctx$getImageData.data;var sy=0;var ey=ih;var py=ih;while(py>sy){var alpha=data[(py-1)*4+3];if(alpha===0){ey=py;}else{sy=py;}py=ey+sy>>1;}var ratio=py/ih;if(ratio===0){return 1;}else{return ratio;}};var drawImageIOSFix=function drawImageIOSFix(ctx,img,sx,sy,sw,sh,dx,dy,dw,dh){ +var vertSquashRatio=detectVerticalSquash(img);return ctx.drawImage(img,sx,sy,sw,sh,dx,dy,dw,dh/vertSquashRatio);};var ExifRestore=function(){function ExifRestore(){_classCallCheck(this,ExifRestore);}_createClass(ExifRestore,null,[{key:"initClass",value:function initClass(){this.KEY_STR='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';}},{key:"encode64",value:function encode64(input){var output='';var chr1=undefined;var chr2=undefined;var chr3='';var enc1=undefined;var enc2=undefined;var enc3=undefined;var enc4='';var i=0;while(true){chr1=input[i++];chr2=input[i++];chr3=input[i++];enc1=chr1>>2;enc2=(chr1&3)<<4|chr2>>4;enc3=(chr2&15)<<2|chr3>>6;enc4=chr3&63;if(isNaN(chr2)){enc3=enc4=64;}else if(isNaN(chr3)){enc4=64;}output=output+this.KEY_STR.charAt(enc1)+this.KEY_STR.charAt(enc2)+this.KEY_STR.charAt(enc3)+this.KEY_STR.charAt(enc4);chr1=chr2=chr3='';enc1=enc2=enc3=enc4='';if(!(irawImageArray.length){break;}}return segments;}},{key:"decode64",value:function decode64(input){var output='';var chr1=undefined;var chr2=undefined;var chr3='';var enc1=undefined;var enc2=undefined;var enc3=undefined;var enc4='';var i=0;var buf=[];var base64test=/[^A-Za-z0-9\+\/\=]/g;if(base64test.exec(input)){console.warn('There were invalid base64 characters in the input text.\nValid base64 characters are A-Z, a-z, 0-9, \'+\', \'/\',and \'=\'\nExpect errors in decoding.'); +}input=input.replace(/[^A-Za-z0-9\+\/\=]/g,'');while(true){enc1=this.KEY_STR.indexOf(input.charAt(i++));enc2=this.KEY_STR.indexOf(input.charAt(i++));enc3=this.KEY_STR.indexOf(input.charAt(i++));enc4=this.KEY_STR.indexOf(input.charAt(i++));chr1=enc1<<2|enc2>>4;chr2=(enc2&15)<<4|enc3>>2;chr3=(enc3&3)<<6|enc4;buf.push(chr1);if(enc3!==64){buf.push(chr2);}if(enc4!==64){buf.push(chr3);}chr1=chr2=chr3='';enc1=enc2=enc3=enc4='';if(!(i=0){newClass=newClass.replace(' '+className+' ',' ');}elem.className=newClass.replace(/^\s+|\s+$/g,'');}},escapeHtml=function(str){var div=document.createElement('div');div.appendChild(document.createTextNode(str)); +return div.innerHTML;},_show=function(elem){elem.style.opacity='';elem.style.display='block';},show=function(elems){if(elems&&!elems.length){return _show(elems);}for(var i=0;i0){setTimeout(tick,interval);}else{elem.style.display='none';}};tick();},fireClick=function(node){if(MouseEvent){var mevt=new MouseEvent('click',{view:window,bubbles:false,cancelable:true});node.dispatchEvent(mevt);}else if(document.createEvent){var evt=document.createEvent('MouseEvents');evt.initEvent('click',false,false);node.dispatchEvent(evt);}else if(document.createEventObject){node.fireEvent('onclick');}else if(typeof node.onclick==='function'){node.onclick();}},stopEventPropagation=function(e){if(typeof e.stopPropagation==='function'){e.stopPropagation();e.preventDefault();}else if(window.event&&window.event.hasOwnProperty('cancelBubble')){window.event.cancelBubble=true;}};var previousActiveElement, +previousDocumentClick,previousWindowKeyDown,lastFocusedButton;window.sweetAlertInitialize=function(){var sweetHTML='

Title

Text

',sweetWrap=document.createElement('div');sweetWrap.innerHTML=sweetHTML;document.body.appendChild(sweetWrap);} +window.sweetAlert=window.swal=function(){if(arguments[0]===undefined){window.console.error('sweetAlert expects at least 1 attribute!');return false;}var params=extend({},defaultParams);switch(typeof arguments[0]){case'string':params.title=arguments[0];params.text=arguments[1]||'';params.type=arguments[2]||'';break;case'object':if(arguments[0].title===undefined){window.console.error('Missing "title" argument!');return false;}params.title=arguments[0].title;params.text=arguments[0].text||defaultParams.text;params.type=arguments[0].type||defaultParams.type;params.allowOutsideClick=arguments[0].allowOutsideClick||defaultParams.allowOutsideClick;params.showCancelButton=arguments[0].showCancelButton!==undefined?arguments[0].showCancelButton:defaultParams.showCancelButton;params.showConfirmButton=arguments[0].showConfirmButton!==undefined?arguments[0].showConfirmButton:defaultParams.showConfirmButton;params.closeOnConfirm=arguments[0].closeOnConfirm!==undefined?arguments[0].closeOnConfirm:defaultParams.closeOnConfirm; +params.closeOnCancel=arguments[0].closeOnCancel!==undefined?arguments[0].closeOnCancel:defaultParams.closeOnCancel;params.timer=arguments[0].timer||defaultParams.timer;params.confirmButtonText=(defaultParams.showCancelButton)?'Confirm':defaultParams.confirmButtonText;params.confirmButtonText=arguments[0].confirmButtonText||defaultParams.confirmButtonText;params.confirmButtonClass=arguments[0].confirmButtonClass||(arguments[0].type?'btn-'+arguments[0].type:null)||defaultParams.confirmButtonClass;params.cancelButtonText=arguments[0].cancelButtonText||defaultParams.cancelButtonText;params.cancelButtonClass=arguments[0].cancelButtonClass||defaultParams.cancelButtonClass;params.containerClass=arguments[0].containerClass||defaultParams.containerClass;params.titleClass=arguments[0].titleClass||defaultParams.titleClass;params.textClass=arguments[0].textClass||defaultParams.textClass;params.imageUrl=arguments[0].imageUrl||defaultParams.imageUrl;params.imageSize=arguments[0].imageSize||defaultParams.imageSize; +params.doneFunction=arguments[1]||null;break;default:window.console.error('Unexpected type of argument! Expected "string" or "object", got '+typeof arguments[0]);return false;}setParameters(params);fixVerticalPosition();openModal();var modal=getModal();var onButtonEvent=function(e){var target=e.target||e.srcElement,targetedConfirm=(target.className.indexOf('confirm')>-1),modalIsVisible=hasClass(modal,'visible'),doneFunctionExists=(params.doneFunction&&modal.getAttribute('data-has-done-function')==='true');switch(e.type){case("click"):if(targetedConfirm&&doneFunctionExists&&modalIsVisible){params.doneFunction(true);if(params.closeOnConfirm){closeModal();}}else if(doneFunctionExists&&modalIsVisible){var functionAsStr=String(params.doneFunction).replace(/\s/g,'');var functionHandlesCancel=functionAsStr.substring(0,9)==="function("&&functionAsStr.substring(9,10)!==")";if(functionHandlesCancel){params.doneFunction(false);}if(params.closeOnCancel){closeModal();}}else{closeModal();}break;}}; +var $buttons=modal.querySelectorAll('button');for(var i=0;i<$buttons.length;i++){$buttons[i].onclick=onButtonEvent;}previousDocumentClick=document.onclick;document.onclick=function(e){var target=e.target||e.srcElement;var clickedOnModal=(modal===target),clickedOnModalChild=isDescendant(modal,e.target),modalIsVisible=hasClass(modal,'visible'),outsideClickIsAllowed=modal.getAttribute('data-allow-ouside-click')==='true';if(!clickedOnModal&&!clickedOnModalChild&&modalIsVisible&&outsideClickIsAllowed){closeModal();}};var $okButton=modal.querySelector('button.confirm'),$cancelButton=modal.querySelector('button.cancel'),$modalButtons=modal.querySelectorAll('button:not([type=hidden])');function handleKeyDown(e){var keyCode=e.keyCode||e.which;if([9,13,32,27].indexOf(keyCode)===-1){return;}var $targetElement=e.target||e.srcElement;var btnIndex=-1;for(var i=0;i<$modalButtons.length;i++){if($targetElement===$modalButtons[i]){btnIndex=i;break;}}if(keyCode===9){if(btnIndex===-1){$targetElement=$okButton; +}else{if(btnIndex===$modalButtons.length-1){$targetElement=$modalButtons[0];}else{$targetElement=$modalButtons[btnIndex+1];}}stopEventPropagation(e);$targetElement.focus();}else{if(keyCode===13||keyCode===32){if(btnIndex===-1){$targetElement=$okButton;}else{$targetElement=undefined;}}else if(keyCode===27&&!($cancelButton.hidden||$cancelButton.style.display==='none')){$targetElement=$cancelButton;}else{$targetElement=undefined;}if($targetElement!==undefined){fireClick($targetElement,e);}}}previousWindowKeyDown=window.onkeydown;window.onkeydown=handleKeyDown;function handleOnBlur(e){var $targetElement=e.target||e.srcElement,$focusElement=e.relatedTarget,modalIsVisible=hasClass(modal,'visible'),bootstrapModalIsVisible=document.querySelector('.control-popup.modal')||false;if(bootstrapModalIsVisible){return;}if(modalIsVisible){var btnIndex=-1;if($focusElement!==null){for(var i=0;i<$modalButtons.length;i++){if($focusElement===$modalButtons[i]){btnIndex=i;break;}}if(btnIndex===-1){ +$targetElement.focus();}}else{lastFocusedButton=$targetElement;}}}$okButton.onblur=handleOnBlur;$cancelButton.onblur=handleOnBlur;window.onfocus=function(){window.setTimeout(function(){if(lastFocusedButton!==undefined){lastFocusedButton.focus();lastFocusedButton=undefined;}},0);};};window.swal.setDefaults=function(userParams){if(!userParams){throw new Error('userParams is required');}if(typeof userParams!=='object'){throw new Error('userParams has to be a object');}extend(defaultParams,userParams);};window.swal.close=function(){closeModal();} +function setParameters(params){var modal=getModal();var $title=modal.querySelector('h2'),$text=modal.querySelector('p'),$cancelBtn=modal.querySelector('button.cancel'),$confirmBtn=modal.querySelector('button.confirm');$title.innerHTML=escapeHtml(params.title).split("\n").join("
");$text.innerHTML=escapeHtml(params.text||'').split("\n").join("
");if(params.text){show($text);}hide(modal.querySelectorAll('.icon'));if(params.type){var validType=false;for(var i=0;iw)&&w>0){nw=w;nh=(w/$obj.width())*$obj.height();}if((nh>h)&&h>0){nh=h;nw=(h/$obj.height())*$obj.width();}xscale=$obj.width()/nw;yscale=$obj.height()/nh;$obj.width(nw).height(nh);}function unscale(c){return{x:c.x*xscale,y:c.y*yscale,x2:c.x2*xscale,y2:c.y2*yscale,w:c.w*xscale,h:c.h*yscale};}function doneSelect(pos){var c=Coords.getFixed();if((c.w>options.minSelect[0])&&(c.h>options.minSelect[1])){Selection.enableHandles();Selection.done();}else{Selection.release();}Tracker.setCursor(options.allowSelect?'crosshair':'default');}function newSelection(e){if(options.disabled){ +return false;}if(!options.allowSelect){return false;}btndown=true;docOffset=getPos($img);Selection.disableHandles();Tracker.setCursor('crosshair');var pos=mouseAbs(e);Coords.setPressed(pos);Selection.update();Tracker.activateHandlers(selectDrag,doneSelect,e.type.substring(0,5)==='touch');KeyManager.watchKeys();e.stopPropagation();e.preventDefault();return false;}function selectDrag(pos){Coords.setCurrent(pos);Selection.update();}function newTracker(){var trk=$('
').addClass(cssClass('tracker'));if(is_msie){trk.css({opacity:0,backgroundColor:'white'});}return trk;}if(typeof(obj)!=='object'){obj=$(obj)[0];}if(typeof(opt)!=='object'){opt={};}setOptions(opt);var img_css={border:'none',visibility:'visible',margin:0,padding:0,position:'absolute',top:0,left:0};var $origimg=$(obj),img_mode=true;if(obj.tagName=='IMG'){if($origimg[0].width!=0&&$origimg[0].height!=0){$origimg.width($origimg[0].width);$origimg.height($origimg[0].height);}else{var tempImage=new Image();tempImage.src=$origimg[0].src; +$origimg.width(tempImage.width);$origimg.height(tempImage.height);}var $img=$origimg.clone().removeAttr('id').css(img_css).show();$img.width($origimg.width());$img.height($origimg.height());$origimg.after($img).hide();}else{$img=$origimg.css(img_css).show();img_mode=false;if(options.shade===null){options.shade=true;}}presize($img,options.boxWidth,options.boxHeight);var boundx=$img.width(),boundy=$img.height(),$div=$('
').width(boundx).height(boundy).addClass(cssClass('holder')).css({position:'relative',backgroundColor:options.bgColor}).insertAfter($origimg).append($img);if(options.addClass){$div.addClass(options.addClass);}var $img2=$('
'),$img_holder=$('
').width('100%').height('100%').css({zIndex:310,position:'absolute',overflow:'hidden'}),$hdl_holder=$('
').width('100%').height('100%').css('zIndex',320),$sel=$('
').css({position:'absolute',zIndex:600}).dblclick(function(){var c=Coords.getFixed();options.onDblClick.call(api,c);}).insertBefore($img).append($img_holder,$hdl_holder); +if(img_mode){$img2=$('').attr('src',$img.attr('src')).css(img_css).width(boundx).height(boundy),$img_holder.append($img2);}if(ie6mode){$sel.css({overflowY:'hidden'});}var bound=options.boundary;var $trk=newTracker().width(boundx+(bound*2)).height(boundy+(bound*2)).css({position:'absolute',top:px(-bound),left:px(-bound),zIndex:290}).mousedown(newSelection);var bgcolor=options.bgColor,bgopacity=options.bgOpacity,xlimit,ylimit,xmin,ymin,xscale,yscale,enabled=true,btndown,animating,shift_down;docOffset=getPos($img);var Touch=(function(){function hasTouchSupport(){var support={},events=['touchstart','touchmove','touchend'],el=document.createElement('div'),i;try{for(i=0;ix1+ox){ox-=ox+x1;}if(0>y1+oy){oy-=oy+y1;}if(boundyboundx){xx=boundx;h=Math.abs((xx-x1)/aspect);yy=rh<0?y1-h:h+y1;}}else{xx=x2;h=rwa/aspect;yy=rh<0?y1-h:y1+h;if(yy<0){yy=0;w=Math.abs((yy-y1)*aspect); +xx=rw<0?x1-w:w+x1;}else if(yy>boundy){yy=boundy;w=Math.abs(yy-y1)*aspect;xx=rw<0?x1-w:w+x1;}}if(xx>x1){if(xx-x1max_x){xx=x1+max_x;}if(yy>y1){yy=y1+(xx-x1)/aspect;}else{yy=y1-(xx-x1)/aspect;}}else if(xxmax_x){xx=x1-max_x;}if(yy>y1){yy=y1+(x1-xx)/aspect;}else{yy=y1-(x1-xx)/aspect;}}if(xx<0){x1-=xx;xx=0;}else if(xx>boundx){x1-=xx-boundx;xx=boundx;}if(yy<0){y1-=yy;yy=0;}else if(yy>boundy){y1-=yy-boundy;yy=boundy;}return makeObj(flipCoords(x1,y1,xx,yy));}function rebound(p){if(p[0]<0)p[0]=0;if(p[1]<0)p[1]=0;if(p[0]>boundx)p[0]=boundx;if(p[1]>boundy)p[1]=boundy;return[Math.round(p[0]),Math.round(p[1])];}function flipCoords(x1,y1,x2,y2){var xa=x1,xb=x2,ya=y1,yb=y2;if(x2xlimit)){x2=(xsize>0)?(x1+xlimit):(x1-xlimit);}if(ylimit&&(Math.abs(ysize)>ylimit)){y2=(ysize>0)?(y1+ylimit):(y1-ylimit); +}if(ymin/yscale&&(Math.abs(ysize)0)?(y1+ymin/yscale):(y1-ymin/yscale);}if(xmin/xscale&&(Math.abs(xsize)0)?(x1+xmin/xscale):(x1-xmin/xscale);}if(x1<0){x2-=x1;x1-=x1;}if(y1<0){y2-=y1;y1-=y1;}if(x2<0){x1-=x2;x2-=x2;}if(y2<0){y1-=y2;y2-=y2;}if(x2>boundx){delta=x2-boundx;x1-=delta;x2-=delta;}if(y2>boundy){delta=y2-boundy;y1-=delta;y2-=delta;}if(x1>boundx){delta=x1-boundy;y2-=delta;y1-=delta;}if(y1>boundy){delta=y1-boundy;y2-=delta;y1-=delta;}return makeObj(flipCoords(x1,y1,x2,y2));}function makeObj(a){return{x:a[0],y:a[1],x2:a[2],y2:a[3],w:a[2]-a[0],h:a[3]-a[1]};}return{flipCoords:flipCoords,setPressed:setPressed,setCurrent:setCurrent,getOffset:getOffset,moveOffset:moveOffset,getCorner:getCorner,getFixed:getFixed};}());var Shade=(function(){var enabled=false,holder=$('
').css({position:'absolute',zIndex:240,opacity:0}),shades={top:createShade(),left:createShade().height(boundy),right:createShade().height(boundy),bottom:createShade()}; +function resizeShades(w,h){shades.left.css({height:px(h)});shades.right.css({height:px(h)});}function updateAuto(){return updateShade(Coords.getFixed());}function updateShade(c){shades.top.css({left:px(c.x),width:px(c.w),height:px(c.y)});shades.bottom.css({top:px(c.y2),left:px(c.x),width:px(c.w),height:px(boundy-c.y2)});shades.right.css({left:px(c.x2),width:px(boundx-c.x2)});shades.left.css({width:px(c.x)});}function createShade(){return $('
').css({position:'absolute',backgroundColor:options.shadeColor||options.bgColor}).appendTo(holder);}function enableShade(){if(!enabled){enabled=true;holder.insertBefore($img);updateAuto();Selection.setBgOpacity(1,0,1);$img2.hide();setBgColor(options.shadeColor||options.bgColor,1);if(Selection.isAwake()){setOpacity(options.bgOpacity,1);}else setOpacity(1,1);}}function setBgColor(color,now){colorChangeMacro(getShades(),color,now);}function disableShade(){if(enabled){holder.remove();$img2.show();enabled=false;if(Selection.isAwake()){Selection.setBgOpacity(options.bgOpacity,1,1); +}else{Selection.setBgOpacity(1,1,1);Selection.disableHandles();}colorChangeMacro($div,0,1);}}function setOpacity(opacity,now){if(enabled){if(options.bgFade&&!now){holder.animate({opacity:1-opacity},{queue:false,duration:options.fadeTime});}else holder.css({opacity:1-opacity});}}function refreshAll(){options.shade?enableShade():disableShade();if(Selection.isAwake())setOpacity(options.bgOpacity);}function getShades(){return holder.children();}return{update:updateAuto,updateRaw:updateShade,getShades:getShades,setBgColor:setBgColor,enable:enableShade,disable:disableShade,resize:resizeShades,refresh:refreshAll,opacity:setOpacity};}());var Selection=(function(){var awake,hdep=370,borders={},handle={},dragbar={},seehandles=false;function insertBorder(type){var jq=$('
').css({position:'absolute',opacity:options.borderOpacity}).addClass(cssClass(type));$img_holder.append(jq);return jq;}function dragDiv(ord,zi){var jq=$('
').mousedown(createDragger(ord)).css({cursor:ord+'-resize', +position:'absolute',zIndex:zi}).addClass('ord-'+ord);if(Touch.support){jq.bind('touchstart.jcrop',Touch.createDragger(ord));}$hdl_holder.append(jq);return jq;}function insertHandle(ord){var hs=options.handleSize,div=dragDiv(ord,hdep++).css({opacity:options.handleOpacity}).addClass(cssClass('handle'));if(hs){div.width(hs).height(hs);}return div;}function insertDragbar(ord){return dragDiv(ord,hdep++).addClass('jcrop-dragbar');}function createDragbars(li){var i;for(i=0;i').css({position:'fixed',left:'-120px',width:'12px'}).addClass('jcrop-keymgr'),$keywrap=$('
').css({position:'absolute',overflow:'hidden'}).append($keymgr);function watchKeys(){if(options.keySupport){$keymgr.show();$keymgr.focus();}}function onBlur(e){$keymgr.hide();}function doNudge(e,x,y){if(options.allowMove){Coords.moveOffset([x,y]);Selection.updateVisible(true);}e.preventDefault();e.stopPropagation();}function parseKey(e){if(e.ctrlKey||e.metaKey){return true;}shift_down=e.shiftKey?true:false;var nudge=shift_down?10:1;switch(e.keyCode){case 37:doNudge(e,-nudge,0);break;case 39:doNudge(e,nudge,0);break; +case 38:doNudge(e,0,-nudge);break;case 40:doNudge(e,0,nudge);break;case 27:if(options.allowSelect)Selection.release();break;case 9:return true;}return false;}if(options.keySupport){$keymgr.keydown(parseKey).blur(onBlur);if(ie6mode||!options.fixedSupport){$keymgr.css({position:'absolute',left:'-20px'});$keywrap.append($keymgr).insertBefore($img);}else{$keymgr.insertBefore($img);}}return{watchKeys:watchKeys};}());function setClass(cname){$div.removeClass().addClass(cssClass('holder')).addClass(cname);}function animateTo(a,callback){var x1=a[0]/xscale,y1=a[1]/yscale,x2=a[2]/xscale,y2=a[3]/yscale;if(animating){return;}var animto=Coords.flipCoords(x1,y1,x2,y2),c=Coords.getFixed(),initcr=[c.x,c.y,c.x2,c.y2],animat=initcr,interv=options.animationDelay,ix1=animto[0]-initcr[0],iy1=animto[1]-initcr[1],ix2=animto[2]-initcr[2],iy2=animto[3]-initcr[3],pcent=0,velocity=options.swingSpeed;x1=animat[0];y1=animat[1];x2=animat[2];y2=animat[3];Selection.animMode(true);var anim_timer;function queueAnimator(){ +window.setTimeout(animator,interv);}var animator=(function(){return function(){pcent+=(100-pcent)/velocity;animat[0]=Math.round(x1+((pcent/100)*ix1));animat[1]=Math.round(y1+((pcent/100)*iy1));animat[2]=Math.round(x2+((pcent/100)*ix2));animat[3]=Math.round(y2+((pcent/100)*iy2));if(pcent>=99.8){pcent=100;}if(pcent<100){setSelectRaw(animat);queueAnimator();}else{Selection.done();Selection.animMode(false);if(typeof(callback)==='function'){callback.call(api);}}};}());queueAnimator();}function setSelect(rect){setSelectRaw([rect[0]/xscale,rect[1]/yscale,rect[2]/xscale,rect[3]/yscale]);options.onSelect.call(api,unscale(Coords.getFixed()));Selection.enableHandles();}function setSelectRaw(l){Coords.setPressed([l[0],l[1]]);Coords.setCurrent([l[2],l[3]]);Selection.update();}function tellSelect(){return unscale(Coords.getFixed());}function tellScaled(){return Coords.getFixed();}function setOptionsNew(opt){setOptions(opt);interfaceUpdate();}function disableCrop(){options.disabled=true;Selection.disableHandles(); +Selection.setCursor('default');Tracker.setCursor('default');}function enableCrop(){options.disabled=false;interfaceUpdate();}function cancelCrop(){Selection.done();Tracker.activateHandlers(null,null);}function destroy(){$(document).unbind('touchstart.jcrop-ios',Touch.fixTouchSupport);$div.remove();$origimg.show();$origimg.css('visibility','visible');$(obj).removeData('Jcrop');}function setImage(src,callback){Selection.release();disableCrop();var img=new Image();img.onload=function(){var iw=img.width;var ih=img.height;var bw=options.boxWidth;var bh=options.boxHeight;$img.width(iw).height(ih);$img.attr('src',src);$img2.attr('src',src);presize($img,bw,bh);boundx=$img.width();boundy=$img.height();$img2.width(boundx).height(boundy);$trk.width(boundx+(bound*2)).height(boundy+(bound*2));$div.width(boundx).height(boundy);Shade.resize(boundx,boundy);enableCrop();if(typeof(callback)==='function'){callback.call(api);}};img.src=src;}function colorChangeMacro($obj,color,now){var mycolor=color||options.bgColor; +if(options.bgFade&&supportsColorFade()&&options.fadeTime&&!now){$obj.animate({backgroundColor:mycolor},{queue:false,duration:options.fadeTime});}else{$obj.css('backgroundColor',mycolor);}}function interfaceUpdate(alt){if(options.allowResize){if(alt){Selection.enableOnly();}else{Selection.enableHandles();}}else{Selection.disableHandles();}Tracker.setCursor(options.allowSelect?'crosshair':'default');Selection.setCursor(options.allowMove?'move':'default');if(options.hasOwnProperty('trueSize')){xscale=options.trueSize[0]/boundx;yscale=options.trueSize[1]/boundy;}if(options.hasOwnProperty('setSelect')){setSelect(options.setSelect);Selection.done();delete(options.setSelect);}Shade.refresh();if(options.bgColor!=bgcolor){colorChangeMacro(options.shade?Shade.getShades():$div,options.shade?(options.shadeColor||options.bgColor):options.bgColor);bgcolor=options.bgColor;}if(bgopacity!=options.bgOpacity){bgopacity=options.bgOpacity;if(options.shade)Shade.refresh();else Selection.setBgOpacity(bgopacity); +}xlimit=options.maxSize[0]||0;ylimit=options.maxSize[1]||0;xmin=options.minSize[0]||0;ymin=options.minSize[1]||0;if(options.hasOwnProperty('outerImage')){$img.attr('src',options.outerImage);delete(options.outerImage);}Selection.refresh();}if(Touch.support)$trk.bind('touchstart.jcrop',Touch.newSelection);$hdl_holder.hide();interfaceUpdate(true);var api={setImage:setImage,animateTo:animateTo,setSelect:setSelect,setOptions:setOptionsNew,tellSelect:tellSelect,tellScaled:tellScaled,setClass:setClass,disable:disableCrop,enable:enableCrop,cancel:cancelCrop,release:Selection.release,destroy:destroy,focus:KeyManager.watchKeys,getBounds:function(){return[boundx*xscale,boundy*yscale];},getWidgetSize:function(){return[boundx,boundy];},getScaleFactor:function(){return[xscale,yscale];},getOptions:function(){return options;},ui:{holder:$div,selection:$sel}};if(is_msie)$div.bind('selectstart',function(){return false;});$origimg.data('Jcrop',api);return api;};$.fn.Jcrop=function(options,callback){var api; +this.each(function(){if($(this).data('Jcrop')){if(options==='api')return $(this).data('Jcrop');else $(this).data('Jcrop').setOptions(options);}else{if(this.tagName=='IMG')$.Jcrop.Loader(this,function(){$(this).css({display:'block',visibility:'hidden'});api=$.Jcrop(this,options);if($.isFunction(callback))callback.call(api);});else{$(this).css({display:'block',visibility:'hidden'});api=$.Jcrop(this,options);if($.isFunction(callback))callback.call(api);}}});return this;};$.Jcrop.Loader=function(imgobj,success,error){var $img=$(imgobj),img=$img[0];function completeCheck(){if(img.complete){$img.unbind('.jcloader');if($.isFunction(success))success.call(img);}else window.setTimeout(completeCheck,50);}$img.bind('load.jcloader',completeCheck).bind('error.jcloader',function(e){$img.unbind('.jcloader');if($.isFunction(error))error.call(img);});if(img.complete&&$.isFunction(success)){$img.unbind('.jcloader');success.call(img);}};$.Jcrop.defaults={allowSelect:true,allowMove:true,allowResize:true, +trackDocument:true,baseClass:'jcrop',addClass:null,bgColor:'black',bgOpacity:0.6,bgFade:false,borderOpacity:0.4,handleOpacity:0.5,handleSize:null,aspectRatio:0,keySupport:true,createHandles:['n','s','e','w','nw','ne','se','sw'],createDragbars:['n','s','e','w'],createBorders:['n','s','e','w'],drawBorders:true,dragEdges:true,fixedSupport:true,touchSupport:null,shade:null,boxWidth:0,boxHeight:0,boundary:2,fadeTime:400,animationDelay:20,swingSpeed:3,minSelect:[0,0],maxSize:[0,0],minSize:[0,0],onChange:function(){},onSelect:function(){},onDblClick:function(){},onRelease:function(){}};}(jQuery));!function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;(function(){function S(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:"0"<=a&&a<="7"?parseInt(e.substring(1),8):a==="u"||a==="x"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return e==="\\"||e==="-"||e==="]"||e==="^"?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),e=[],a= +b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,f=b.length;a122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;ah[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(g(h[1])));c.push("]");return c.join("")}function s(e){for(var a=e.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],f=0,h=0;f=2&&e==="["?a[f]=b(l):e!=="\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k=5&&"lang-"===w.substring(0,5))&&!(t&&typeof t[1]==="string"))f=!1,w="src";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c=0;)b[n.charAt(e)]=r;r=r[1];n=""+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\S\s]/);s=S(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&g.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),g.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,q])):d.push(["com", +/^#[^\n\r]*/,q,"#"]));a.cStyleComments&&(g.push(["com",/^\/\/[^\n\r]*/,q]),g.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?"":"\n\r")?".":"[\\S\\s]";g.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+s+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/, +q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d=c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"], +O=[N,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],E=[E,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],P=[y,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],Q=[y,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],W=[y,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],y=[y,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],R=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/, +V=/\S/,X=v({keywords:[M,O,E,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",P,Q,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,["default-code"]);p(C([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);p(C([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/], +["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);p(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);p(v({keywords:M,hashComments:!0,cStyleComments:!0,types:R}),["c","cc","cpp","cxx","cyc","m"]);p(v({keywords:"null,true,false"}),["json"]);p(v({keywords:O,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:R}),["cs"]);p(v({keywords:N,cStyleComments:!0}),["java"]);p(v({keywords:y,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(v({keywords:P,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(v({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);p(v({keywords:Q, +hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(v({keywords:E,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(v({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(v({keywords:W,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]);p(C([],[["str",/^[\S\s]+/]]),["regex"]);var Y=D.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:v,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:D.prettyPrintOne=function(a,d,g){var b=document.createElement("div");b.innerHTML="
"+a+"
";b=b.firstChild;g&&J(b,g,!0);K({h:d,j:g,c:b,i:1}); +return b.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function g(){for(var b=D.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;i') +this.registerHandlers()} +MediaManagerPopup.prototype.registerHandlers=function(){this.$popupRootElement.one('hide.oc.popup',this.proxy(this.onPopupHidden)) +this.$popupRootElement.one('shown.oc.popup',this.proxy(this.onPopupShown))} +MediaManagerPopup.prototype.unregisterHandlers=function(){this.$popupElement.off('popupcommand',this.proxy(this.onPopupCommand)) +this.$popupRootElement.off('popupcommand',this.proxy(this.onPopupCommand))} +MediaManagerPopup.prototype.show=function(){var data={bottomToolbar:this.options.bottomToolbar?1:0,cropAndInsertButton:this.options.cropAndInsertButton?1:0,mode:this.options.mode||'all',} +this.$popupRootElement.popup({extraData:data,size:'adaptive',adaptiveHeight:true,handler:this.options.alias+'::onLoadPopup'})} +MediaManagerPopup.prototype.hide=function(){if(this.$popupElement)this.$popupElement.trigger('close.oc.popup')} +MediaManagerPopup.prototype.getMediaManagerElement=function(){return this.$popupElement.find('[data-control="media-manager"]')} +MediaManagerPopup.prototype.insertMedia=function(){var items=this.getMediaManagerElement().mediaManager('getSelectedItems') +if(this.options.onInsert!==undefined)this.options.onInsert.call(this,items)} +MediaManagerPopup.prototype.insertCroppedImage=function(imageItem){if(this.options.onInsert!==undefined)this.options.onInsert.call(this,[imageItem])} +MediaManagerPopup.prototype.onPopupHidden=function(event,element,popup){var mediaManager=this.getMediaManagerElement() +mediaManager.mediaManager('dispose') +mediaManager.remove() +$(document).trigger('mousedown') +this.dispose() +if(this.options.onClose!==undefined)this.options.onClose.call(this)} +MediaManagerPopup.prototype.onPopupShown=function(event,element,popup){this.$popupElement=popup +this.$popupElement.on('popupcommand',this.proxy(this.onPopupCommand)) +this.getMediaManagerElement().mediaManager('selectFirstItem')} +MediaManagerPopup.prototype.onPopupCommand=function(ev,command,param){switch(command){case'insert':this.insertMedia() +break;case'insert-cropped':this.insertCroppedImage(param) +break;}return false} +MediaManagerPopup.DEFAULTS={alias:undefined,bottomToolbar:true,cropAndInsertButton:false,onInsert:undefined,onClose:undefined} +$.wn.mediaManager.popup=MediaManagerPopup}(window.jQuery);if($.wn===undefined)$.wn={} +if($.oc===undefined)$.oc=$.wn +if($.wn.langMessages===undefined)$.wn.langMessages={} +$.wn.lang=(function(lang,messages){lang.load=function(locale){if(messages[locale]===undefined){messages[locale]={}}lang.loadedMessages=messages[locale]} +lang.get=function(name,defaultValue){if(!name)return +var result=lang.loadedMessages +if(!defaultValue)defaultValue=name +$.each(name.split('.'),function(index,value){if(result[value]===undefined){result=defaultValue +return false}result=result[value]}) +return result} +if(lang.locale===undefined){lang.locale=$('html').attr('lang')||'en'}if(lang.loadedMessages===undefined){lang.load(lang.locale)}return lang})($.wn.lang||{},$.wn.langMessages);(function($){if($.wn===undefined)$.wn={} +if($.oc===undefined)$.oc=$.wn +$.wn.alert=function alert(message){swal({title:message,confirmButtonClass:'btn-primary'})} +$.wn.confirm=function confirm(message,callback){swal({title:message,showCancelButton:true,confirmButtonClass:'btn-primary'},callback)}})(jQuery);$(window).on('ajaxErrorMessage',function(event,message){if(!message)return +$.wn.alert(message) +event.preventDefault()}) +$(window).on('ajaxConfirmMessage',function(event,message){if(!message)return +$.wn.confirm(message,function(isConfirm){isConfirm?event.promise.resolve():event.promise.reject()}) +event.preventDefault() +return true}) +$(document).ready(function(){if(!window.swal)return +var swal=window.swal +window.sweetAlert=window.swal=function(message,callback){if(typeof message==='object'){message.confirmButtonText=message.confirmButtonText||$.wn.lang.get('alert.confirm_button_text') +message.cancelButtonText=message.cancelButtonText||$.wn.lang.get('alert.cancel_button_text')}else{message={title:message,confirmButtonText:$.wn.lang.get('alert.confirm_button_text'),cancelButtonText:$.wn.lang.get('alert.cancel_button_text')}}swal(message,callback)}})+function($){"use strict";var Base=$.wn.foundation.base,BaseProto=Base.prototype +var Scrollpad=function(element,options){this.$el=$(element) +this.scrollbarElement=null +this.dragHandleElement=null +this.scrollContentElement=null +this.contentElement=null +this.options=options +this.scrollbarSize=null +this.updateScrollbarTimer=null +this.dragOffset=null +Base.call(this) +this.init() +$.wn.foundation.controlUtils.markDisposable(element)} +Scrollpad.prototype=Object.create(BaseProto) +Scrollpad.prototype.constructor=Scrollpad +Scrollpad.prototype.dispose=function(){this.unregisterHandlers() +this.$el.get(0).removeChild(this.scrollbarElement) +this.$el.removeData('oc.scrollpad') +this.$el=null +this.scrollbarElement=null +this.dragHandleElement=null +this.scrollContentElement=null +this.contentElement=null +BaseProto.dispose.call(this)} +Scrollpad.prototype.scrollToStart=function(){var scrollAttr=this.options.direction=='vertical'?'scrollTop':'scrollLeft' +this.scrollContentElement[scrollAttr]=0} +Scrollpad.prototype.update=function(){this.updateScrollbarSize()} +Scrollpad.prototype.init=function(){this.build() +this.setScrollContentSize() +this.registerHandlers()} +Scrollpad.prototype.build=function(){var el=this.$el.get(0) +this.scrollContentElement=el.children[0] +this.contentElement=this.scrollContentElement.children[0] +this.$el.prepend('
') +this.scrollbarElement=el.querySelector('.scrollpad-scrollbar') +this.dragHandleElement=el.querySelector('.scrollpad-scrollbar > .drag-handle')} +Scrollpad.prototype.registerHandlers=function(){this.$el.on('mouseenter',this.proxy(this.onMouseEnter)) +this.$el.on('mouseleave',this.proxy(this.onMouseLeave)) +this.$el.one('dispose-control',this.proxy(this.dispose)) +this.scrollContentElement.addEventListener('scroll',this.proxy(this.onScroll)) +this.dragHandleElement.addEventListener('mousedown',this.proxy(this.onStartDrag))} +Scrollpad.prototype.unregisterHandlers=function(){this.$el.off('mouseenter',this.proxy(this.onMouseEnter)) +this.$el.off('mouseleave',this.proxy(this.onMouseLeave)) +this.$el.off('dispose-control',this.proxy(this.dispose)) +this.scrollContentElement.removeEventListener('scroll',this.proxy(this.onScroll)) +this.dragHandleElement.removeEventListener('mousedown',this.proxy(this.onStartDrag)) +document.removeEventListener('mousemove',this.proxy(this.onMouseMove)) +document.removeEventListener('mouseup',this.proxy(this.onEndDrag))} +Scrollpad.prototype.setScrollContentSize=function(){var scrollbarSize=this.getScrollbarSize() +if(this.options.direction=='vertical')this.scrollContentElement.setAttribute('style','margin-right: -'+scrollbarSize+'px') +else this.scrollContentElement.setAttribute('style','margin-bottom: -'+scrollbarSize+'px')} +Scrollpad.prototype.getScrollbarSize=function(){if(this.scrollbarSize!==null)return this.scrollbarSize +var testerElement=document.createElement('div') +testerElement.setAttribute('class','scrollpad-scrollbar-size-tester') +testerElement.appendChild(document.createElement('div')) +document.body.appendChild(testerElement) +var width=testerElement.offsetWidth,innerWidth=testerElement.querySelector('div').offsetWidth +document.body.removeChild(testerElement) +if(width===innerWidth&&navigator.userAgent.toLowerCase().indexOf('firefox')>-1)return this.scrollbarSize=17 +return this.scrollbarSize=width-innerWidth} +Scrollpad.prototype.updateScrollbarSize=function(){this.scrollbarElement.removeAttribute('data-hidden') +var contentSize=this.options.direction=='vertical'?this.contentElement.scrollHeight:this.contentElement.scrollWidth,scrollOffset=this.options.direction=='vertical'?this.scrollContentElement.scrollTop:this.scrollContentElement.scrollLeft,scrollbarSize=this.options.direction=='vertical'?this.scrollbarElement.offsetHeight:this.scrollbarElement.offsetWidth,scrollbarRatio=scrollbarSize/contentSize,handleOffset=Math.round(scrollbarRatio*scrollOffset)+2,handleSize=Math.floor(scrollbarRatio*(scrollbarSize-2))-2;if(scrollbarSize1)dragPerc=1 +var scrollPos=dragPerc*contentSize;this.scrollContentElement[scrollAttr]=scrollPos} +Scrollpad.prototype.onEndDrag=function(ev){document.removeEventListener('mousemove',this.proxy(this.onMouseMove)) +document.removeEventListener('mouseup',this.proxy(this.onEndDrag))} +Scrollpad.DEFAULTS={direction:'vertical'} +var old=$.fn.scrollpad +$.fn.scrollpad=function(option){var args=Array.prototype.slice.call(arguments,1),result=undefined +this.each(function(){var $this=$(this) +var data=$this.data('oc.scrollpad') +var options=$.extend({},Scrollpad.DEFAULTS,$this.data(),typeof option=='object'&&option) +if(!data)$this.data('oc.scrollpad',(data=new Scrollpad(this,options))) +if(typeof option=='string')result=data[option].apply(data,args) +if(typeof result!='undefined')return false}) +return result?result:this} +$.fn.scrollpad.Constructor=Scrollpad +$.fn.scrollpad.noConflict=function(){$.fn.scrollpad=old +return this} +$(document).on('render',function(){$('div[data-control=scrollpad]').scrollpad()})}(window.jQuery);+function($){"use strict";var VerticalMenu=function(element,toggle,options){this.$el=$(element) +this.body=$('body') +this.toggle=$(toggle) +this.options=options||{} +this.options=$.extend({},VerticalMenu.DEFAULTS,this.options) +this.wrapper=$(this.options.contentWrapper) +this.breakpoint=options.breakpoint +this.menuPanel=$('
').appendTo('body').addClass(this.options.collapsedMenuClass).css('width',0) +this.menuContainer=$('
').appendTo(this.menuPanel).css('display','none') +this.menuElement=this.$el.clone().appendTo(this.menuContainer).css('width','auto') +var self=this +this.toggle.click(function(){if(!self.body.hasClass(self.options.bodyMenuOpenClass)){var wrapperWidth=self.wrapper.outerWidth() +self.menuElement.dragScroll('goToStart') +self.wrapper.css({'position':'absolute','min-width':self.wrapper.width(),'height':'100%'}) +self.body.addClass(self.options.bodyMenuOpenClass) +self.menuContainer.css('display','block') +self.wrapper.animate({'left':self.options.menuWidth},{duration:200,queue:false}) +self.menuPanel.animate({'width':self.options.menuWidth},{duration:200,queue:false,complete:function(){self.menuElement.css('width',self.options.menuWidth)}})}else{closeMenu()}return false}) +this.wrapper.click(function(){if(self.body.hasClass(self.options.bodyMenuOpenClass)){closeMenu() +return false}}) +$(window).resize(function(){if(self.body.hasClass(self.options.bodyMenuOpenClass)){if($(window).width()>self.breakpoint){hideMenu()}}}) +this.menuElement.dragScroll({vertical:true,useNative:true,start:function(){self.menuElement.addClass('drag')},stop:function(){self.menuElement.removeClass('drag')},scrollClassContainer:self.menuPanel,scrollMarkerContainer:self.menuContainer}) +this.menuElement.on('click',function(){if(self.menuElement.hasClass('drag'))return false}) +function hideMenu(){self.body.removeClass(self.options.bodyMenuOpenClass) +self.wrapper.css({'position':'static','min-width':0,'right':0,'height':'100%'}) +self.menuPanel.css('width',0) +self.menuElement.css('width','auto') +self.menuContainer.css('display','none')}function closeMenu(){self.wrapper.animate({'left':0},{duration:200,queue:false}) +self.menuPanel.animate({'width':0},{duration:200,queue:false,complete:hideMenu}) +self.menuElement.animate({'width':0},{duration:200,queue:false})}} +VerticalMenu.DEFAULTS={menuWidth:230,breakpoint:769,bodyMenuOpenClass:'mainmenu-open',collapsedMenuClass:'mainmenu-collapsed',contentWrapper:'#layout-canvas'} +var old=$.fn.verticalMenu +$.fn.verticalMenu=function(toggleSelector,option){return this.each(function(){var $this=$(this) +var data=$this.data('oc.verticalMenu') +var options=typeof option=='object'&&option +if(!data)$this.data('oc.verticalMenu',(data=new VerticalMenu(this,toggleSelector,options))) +if(typeof option=='string')data[option].call($this)})} +$.fn.verticalMenu.Constructor=VerticalMenu +$.fn.verticalMenu.noConflict=function(){$.fn.verticalMenu=old +return this}}(window.jQuery);(function($){$(document).ready(function(){$('nav.navbar').each(function(){var navbar=$(this),nav=$('ul.nav',navbar),collapseMode=navbar.hasClass('navbar-mode-collapse'),isMobile=$('html').hasClass('mobile') +nav.verticalMenu($('a.menu-toggle',navbar),{breakpoint:collapseMode?Infinity:769}) +$('li.with-tooltip:not(.active) > a',navbar).tooltip({container:'body',placement:'bottom',template:''}).on('show.bs.tooltip',function(e){if(isMobile)e.preventDefault()}) +var dragScroll=$('[data-control=toolbar]',navbar).data('oc.dragScroll') +if(dragScroll){dragScroll.goToElement($('ul.nav > li.active',navbar),undefined,{'duration':0})}})})})(jQuery);+function($){"use strict";if($.wn===undefined)$.wn={} +if($.oc===undefined)$.oc=$.wn +var SideNav=function(element,options){this.options=options +this.$el=$(element) +this.$list=$('ul',this.$el) +this.$items=$('li',this.$list) +this.init();} +SideNav.DEFAULTS={activeClass:'active'} +SideNav.prototype.init=function(){var self=this +this.$list.dragScroll({vertical:true,useNative:true,start:function(){self.$list.addClass('drag')},stop:function(){self.$list.removeClass('drag')},scrollClassContainer:self.$el,scrollMarkerContainer:self.$el}) +this.$list.on('click',function(){if(self.$list.hasClass('drag')){return false}})} +SideNav.prototype.unsetActiveItem=function(itemId){this.$items.removeClass(this.options.activeClass)} +SideNav.prototype.setActiveItem=function(itemId){if(!itemId){return}this.$items.removeClass(this.options.activeClass).filter('[data-menu-item='+itemId+']').addClass(this.options.activeClass)} +SideNav.prototype.setCounter=function(itemId,value){var $counter=$('span.counter[data-menu-id="'+itemId+'"]',this.$el) +$counter.removeClass('empty') +$counter.toggleClass('empty',value==0) +$counter.text(value) +return this} +SideNav.prototype.increaseCounter=function(itemId,value){var $counter=$('span.counter[data-menu-id="'+itemId+'"]',this.$el) +var originalValue=parseInt($counter.text()) +if(isNaN(originalValue))originalValue=0 +var newValue=value+originalValue +$counter.toggleClass('empty',newValue==0) +$counter.text(newValue) +return this} +SideNav.prototype.dropCounter=function(itemId){this.setCounter(itemId,0) +return this} +var old=$.fn.sideNav +$.fn.sideNav=function(option){var args=Array.prototype.slice.call(arguments,1),result +this.each(function(){var $this=$(this) +var data=$this.data('oc.sideNav') +var options=$.extend({},SideNav.DEFAULTS,$this.data(),typeof option=='object'&&option) +if(!data)$this.data('oc.sideNav',(data=new SideNav(this,options))) +if(typeof option=='string')result=data[option].apply(data,args) +if(typeof result!='undefined')return false +if($.wn.sideNav===undefined)$.wn.sideNav=data}) +return result?result:this} +$.fn.sideNav.Constructor=SideNav +$.fn.sideNav.noConflict=function(){$.fn.sideNav=old +return this} +$(document).ready(function(){$('[data-control="sidenav"]').sideNav()})}(window.jQuery);+function($){"use strict";var Base=$.wn.foundation.base,BaseProto=Base.prototype +var Scrollbar=function(element,options){var $el=this.$el=$(element),el=$el.get(0),self=this,options=this.options=options||{},sizeName=this.sizeName=options.vertical?'height':'width',isNative=$('html').hasClass('mobile'),isTouch=this.isTouch=Modernizr.touchevents,isScrollable=this.isScrollable=false,isLocked=this.isLocked=false,eventElementName=options.vertical?'pageY':'pageX',dragStart=0,startOffset=0;$.wn.foundation.controlUtils.markDisposable(element) +Base.call(this) +this.$el.one('dispose-control',this.proxy(this.dispose)) +if(isNative){return}this.$scrollbar=$('
').addClass('scrollbar-scrollbar') +this.$track=$('
').addClass('scrollbar-track').appendTo(this.$scrollbar) +this.$thumb=$('
').addClass('scrollbar-thumb').appendTo(this.$track) +$el.addClass('drag-scrollbar').addClass(options.vertical?'vertical':'horizontal').prepend(this.$scrollbar) +if(isTouch){this.$el.on('touchstart',function(event){var touchEvent=event.originalEvent;if(touchEvent.touches.length==1){startDrag(touchEvent.touches[0]) +event.stopPropagation()}})}else{this.$thumb.on('mousedown',function(event){startDrag(event)}) +this.$track.on('mouseup',function(event){moveDrag(event)})}$el.mousewheel(function(event){var offset=self.options.vertical?((event.deltaFactor*event.deltaY)*-1):(event.deltaFactor*event.deltaX) +return!scrollWheel(offset*self.options.scrollSpeed)}) +$el.on('oc.scrollbar.gotoStart',function(event){self.options.vertical?$el.scrollTop(0):$el.scrollLeft(0) +self.update() +event.stopPropagation()}) +$(window).on('resize',$.proxy(this.update,this)) +$(window).on('oc.updateUi',$.proxy(this.update,this)) +function startDrag(event){$('body').addClass('drag-noselect') +$el.trigger('oc.scrollStart') +dragStart=event[eventElementName] +startOffset=self.options.vertical?$el.scrollTop():$el.scrollLeft() +if(isTouch){$(window).on('touchmove.scrollbar',function(event){var touchEvent=event.originalEvent +if(moveDrag(touchEvent.touches[0]))event.preventDefault();});$el.on('touchend.scrollbar',stopDrag)}else{$(window).on('mousemove.scrollbar',function(event){moveDrag(event) +return false}) +$(window).on('mouseup.scrollbar',function(){stopDrag() +return false})}}function moveDrag(event){self.isLocked=true;var offset,dragTo=event[eventElementName] +if(self.isTouch){offset=dragStart-dragTo}else{var ratio=self.getCanvasSize()/self.getViewportSize() +offset=(dragTo-dragStart)*ratio}self.options.vertical?$el.scrollTop(startOffset+offset):$el.scrollLeft(startOffset+offset) +self.setThumbPosition() +return self.options.vertical?el.scrollTop!=startOffset:el.scrollLeft!=startOffset}function stopDrag(){$('body').removeClass('drag-noselect') +$el.trigger('oc.scrollEnd') +$(window).off('.scrollbar')}var isWebkit=$(document.documentElement).hasClass('webkit') +function scrollWheel(offset){startOffset=self.options.vertical?el.scrollTop:el.scrollLeft +$el.trigger('oc.scrollStart') +self.options.vertical?$el.scrollTop(startOffset+offset):$el.scrollLeft(startOffset+offset) +var scrolled=self.options.vertical?el.scrollTop!=startOffset:el.scrollLeft!=startOffset +self.setThumbPosition() +if(!isWebkit){if(self.endScrollTimeout!==undefined){clearTimeout(self.endScrollTimeout) +self.endScrollTimeout=undefined}self.endScrollTimeout=setTimeout(function(){$el.trigger('oc.scrollEnd') +self.endScrollTimeout=undefined},50)}else{$el.trigger('oc.scrollEnd')}return scrolled}setTimeout(function(){self.update()},1);} +Scrollbar.prototype=Object.create(BaseProto) +Scrollbar.prototype.constructor=Scrollbar +Scrollbar.prototype.dispose=function(){this.unregisterHandlers() +BaseProto.dispose.call(this)} +Scrollbar.prototype.unregisterHandlers=function(){} +Scrollbar.DEFAULTS={vertical:true,scrollSpeed:2,animation:true,start:function(){},drag:function(){},stop:function(){}} +Scrollbar.prototype.update=function(){if(!this.$scrollbar)return +this.$scrollbar.hide() +this.setThumbSize() +this.setThumbPosition() +this.$scrollbar.show()} +Scrollbar.prototype.setThumbSize=function(){var properties=this.calculateProperties() +this.isScrollable=!(properties.thumbSizeRatio>=1);this.$scrollbar.toggleClass('disabled',!this.isScrollable) +if(this.options.vertical){this.$track.height(properties.canvasSize) +this.$thumb.height(properties.thumbSize)}else{this.$track.width(properties.canvasSize) +this.$thumb.width(properties.thumbSize)}} +Scrollbar.prototype.setThumbPosition=function(){var properties=this.calculateProperties() +if(this.options.vertical)this.$thumb.css({top:properties.thumbPosition}) +else this.$thumb.css({left:properties.thumbPosition})} +Scrollbar.prototype.calculateProperties=function(){var $el=this.$el,properties={};properties.viewportSize=this.getViewportSize() +properties.canvasSize=this.getCanvasSize() +properties.scrollAmount=(this.options.vertical)?$el.scrollTop():$el.scrollLeft() +properties.thumbSizeRatio=properties.viewportSize/properties.canvasSize +properties.thumbSize=properties.viewportSize*properties.thumbSizeRatio +properties.thumbPositionRatio=properties.scrollAmount/(properties.canvasSize-properties.viewportSize) +properties.thumbPosition=((properties.viewportSize-properties.thumbSize)*properties.thumbPositionRatio)+properties.scrollAmount +if(isNaN(properties.thumbPosition))properties.thumbPosition=0 +return properties;} +Scrollbar.prototype.getViewportSize=function(){return(this.options.vertical)?this.$el.height():this.$el.width();} +Scrollbar.prototype.getCanvasSize=function(){return(this.options.vertical)?this.$el.get(0).scrollHeight:this.$el.get(0).scrollWidth;} +Scrollbar.prototype.gotoElement=function(element,callback){var $el=$(element) +if(!$el.length)return;var self=this,offset=0,animated=false,params={duration:300,queue:false,complete:function(){if(callback!==undefined)callback()}} +if(!this.options.vertical){offset=$el.get(0).offsetLeft-this.$el.scrollLeft() +if(offset<0){this.$el.animate({'scrollLeft':$el.get(0).offsetLeft},params) +animated=true}else{offset=$el.get(0).offsetLeft+$el.outerWidth()-(this.$el.scrollLeft()+this.$el.outerWidth()) +if(offset>0){this.$el.animate({'scrollLeft':$el.get(0).offsetLeft+$el.outerWidth()-this.$el.outerWidth()},params) +animated=true}}}else{offset=$el.get(0).offsetTop-this.$el.scrollTop() +if(this.options.animation){if(offset<0){this.$el.animate({'scrollTop':$el.get(0).offsetTop},params) +animated=true}else{offset=$el.get(0).offsetTop-(this.$el.scrollTop()+this.$el.outerHeight()) +if(offset>0){this.$el.animate({'scrollTop':$el.get(0).offsetTop+$el.outerHeight()-this.$el.outerHeight()},params) +animated=true}}}else{if(offset<0){this.$el.scrollTop($el.get(0).offsetTop)}else{offset=$el.get(0).offsetTop-(this.$el.scrollTop()+this.$el.outerHeight()) +if(offset>0)this.$el.scrollTop($el.get(0).offsetTop+$el.outerHeight()-this.$el.outerHeight())}}}if(!animated&&callback!==undefined)callback() +return this} +Scrollbar.prototype.dispose=function(){this.$el=null +this.$scrollbar=null +this.$track=null +this.$thumb=null} +var old=$.fn.scrollbar +$.fn.scrollbar=function(option){return this.each(function(){var $this=$(this) +var data=$this.data('oc.scrollbar') +var options=$.extend({},Scrollbar.DEFAULTS,$this.data(),typeof option=='object'&&option) +if(!data)$this.data('oc.scrollbar',(data=new Scrollbar(this,options))) +if(typeof option=='string')data[option].call($this)})} +$.fn.scrollbar.Constructor=Scrollbar +$.fn.scrollbar.noConflict=function(){$.fn.scrollbar=old +return this} +$(document).render(function(){$('[data-control=scrollbar]').scrollbar()})}(window.jQuery);+function($){"use strict";var FileList=function(element,options){this.options=options +this.$el=$(element) +this.init();} +FileList.DEFAULTS={ignoreItemClick:false} +FileList.prototype.init=function(){var self=this +this.$el.on('click','li.group > h4 > a, li.group > div.group',function(){self.toggleGroup($(this).closest('li')) +return false;});if(!this.options.ignoreItemClick){this.$el.on('click','li.item > a',function(event){var e=$.Event('open.oc.list',{relatedTarget:$(this).parent().get(0),clickEvent:event}) +self.$el.trigger(e,this) +return false})}this.$el.on('ajaxUpdate',$.proxy(this.update,this))} +FileList.prototype.toggleGroup=function(group){var $group=$(group);$group.attr('data-status')=='expanded'?this.collapseGroup($group):this.expandGroup($group)} +FileList.prototype.collapseGroup=function(group){var $list=$('> ul, > div.subitems',group),self=this;$list.css('overflow','hidden') +$list.animate({'height':0},{duration:100,queue:false,complete:function(){$list.css({'overflow':'visible','display':'none'}) +$(group).attr('data-status','collapsed') +$(window).trigger('resize')}}) +this.sendGroupStatusRequest(group,0);} +FileList.prototype.expandGroup=function(group){var $list=$('> ul, > div.subitems',group),self=this;$list.css({'overflow':'hidden','display':'block','height':0}) +$list.animate({'height':$list[0].scrollHeight},{duration:100,queue:false,complete:function(){$list.css({'overflow':'visible','height':'auto'}) +$(group).attr('data-status','expanded') +$(window).trigger('resize')}}) +this.sendGroupStatusRequest(group,1);} +FileList.prototype.sendGroupStatusRequest=function(group,status){if(this.options.groupStatusHandler!==undefined){var groupId=$(group).data('group-id') +if(groupId===undefined)groupId=$('> h4 a',group).text();$(group).request(this.options.groupStatusHandler,{data:{group:groupId,status:status}})}} +FileList.prototype.markActive=function(dataId){$('li.item',this.$el).removeClass('active') +if(dataId)$('li.item[data-id="'+dataId+'"]',this.$el).addClass('active') +this.dataId=dataId} +FileList.prototype.update=function(){if(this.dataId!==undefined)this.markActive(this.dataId)} +var old=$.fn.fileList +$.fn.fileList=function(option){var args=arguments;return this.each(function(){var $this=$(this) +var data=$this.data('oc.fileList') +var options=$.extend({},FileList.DEFAULTS,$this.data(),typeof option=='object'&&option) +if(!data)$this.data('oc.fileList',(data=new FileList(this,options))) +if(typeof option=='string'){var methodArgs=[];for(var i=1;i0){fixedWidth=0 +$children.each(function(){$el=$(this) +margin=$el.data('oc.layoutMargin') +if(margin===undefined){margin=parseInt($el.css('marginRight'))+parseInt($el.css('marginLeft')) +$el.data('oc.layoutMargin',margin)}fixedWidth+=$el.get(0).offsetWidth+margin}) +$(this).width(fixedWidth) +$(this).trigger('oc.widthFixed')}})} +WinterLayout.prototype.toggleAccountMenu=function(el){var self=this,$el=$(el),$parent=$(el).parent(),$menu=$el.next() +$el.tooltip('hide') +if($menu.hasClass('active')){self.$accountMenuOverlay.remove() +$parent.removeClass('highlight') +$menu.removeClass('active')}else{self.$accountMenuOverlay=$('
').addClass('popover-overlay') +$(document.body).append(self.$accountMenuOverlay) +$parent.addClass('highlight') +$menu.addClass('active') +self.$accountMenuOverlay.one('click',function(){self.$accountMenuOverlay.remove() +$menu.removeClass('active') +$parent.removeClass('highlight')})}} +if($.wn===undefined)$.wn={} +if($.oc===undefined)$.oc=$.wn +$.wn.layout=new WinterLayout() +$(document).ready(function(){$.wn.layout.updateLayout() +window.setTimeout($.wn.layout.updateLayout,100)}) +$(window).on('resize',function(){$.wn.layout.updateLayout()}) +$(window).on('oc.updateUi',function(){$.wn.layout.updateLayout()})})(jQuery);+function($){"use strict";var SidePanelTab=function(element,options){this.options=options +this.$el=$(element) +this.init()} +SidePanelTab.prototype.init=function(){var self=this +this.tabOpenDelay=200 +this.tabOpenTimeout=undefined +this.panelOpenTimeout=undefined +this.$sideNav=$('#layout-sidenav') +this.$sideNavItems=$('ul li',this.$sideNav) +this.$sidePanelItems=$('[data-content-id]',this.$el) +this.sideNavWidth=this.$sideNavItems.outerWidth() +this.mainNavHeight=$('#layout-mainmenu').outerHeight() +this.panelVisible=false +this.visibleItemId=false +this.$fixButton=$('') +this.$fixButton.click(function(){self.fixPanel() +return false}) +$('.fix-button-container',this.$el).append(this.$fixButton) +this.$sideNavItems.click(function(){if($(this).data('no-side-panel')){return}if(Modernizr.touchevents&&$(window).width()this.options.breakpoint&&this.panelFixed()){this.hideSidePanel()}} +SidePanelTab.prototype.updateActiveTab=function(){if($.wn.sideNav===undefined){return}if(!this.panelVisible&&($(window).width() ul, > ol').sortable(sortableOptions)}if($el.hasClass('is-scrollable')){$el.wrapInner($('
').addClass('control-scrollbar')) +var $scrollbar=$el.find('>.control-scrollbar:first') +$scrollbar.scrollbar()}} +SimpleList.DEFAULTS={sortableHandle:null} +var old=$.fn.simplelist +$.fn.simplelist=function(option){return this.each(function(){var $this=$(this) +var data=$this.data('oc.simplelist') +var options=$.extend({},SimpleList.DEFAULTS,$this.data(),typeof option=='object'&&option) +if(!data)$this.data('oc.simplelist',(data=new SimpleList(this,options)))})} +$.fn.simplelist.Constructor=SimpleList +$.fn.simplelist.noConflict=function(){$.fn.simplelist=old +return this} +$(document).render(function(){$('[data-control="simplelist"]').simplelist()})}(window.jQuery);+function($){"use strict";var Base=$.wn.foundation.base,BaseProto=Base.prototype +var TreeListWidget=function(element,options){this.$el=$(element) +this.options=options||{};Base.call(this) +$.wn.foundation.controlUtils.markDisposable(element) +this.init()} +TreeListWidget.prototype=Object.create(BaseProto) +TreeListWidget.prototype.constructor=TreeListWidget +TreeListWidget.prototype.init=function(){var sortableOptions={handle:this.options.handle,nested:this.options.nested,onDrop:this.proxy(this.onDrop),afterMove:this.proxy(this.onAfterMove)} +this.$el.find('> ol').sortable($.extend(sortableOptions,this.options)) +if(!this.options.nested)this.$el.find('> ol ol').sortable($.extend(sortableOptions,this.options)) +this.$el.one('dispose-control',this.proxy(this.dispose))} +TreeListWidget.prototype.dispose=function(){this.unbind() +BaseProto.dispose.call(this)} +TreeListWidget.prototype.unbind=function(){this.$el.off('dispose-control',this.proxy(this.dispose)) +this.$el.find('> ol').sortable('destroy') +if(!this.options.nested){this.$el.find('> ol ol').sortable('destroy')}this.$el.removeData('oc.treelist') +this.$el=null +this.options=null} +TreeListWidget.DEFAULTS={handle:null,nested:true} +TreeListWidget.prototype.onDrop=function($item,container,_super){if(!this.$el){return}this.$el.trigger('move.oc.treelist',{item:$item,container:container}) +_super($item,container)} +TreeListWidget.prototype.onAfterMove=function($placeholder,container,$closestEl){if(!this.$el){return}this.$el.trigger('aftermove.oc.treelist',{placeholder:$placeholder,container:container,closestEl:$closestEl})} +var old=$.fn.treeListWidget +$.fn.treeListWidget=function(option){var args=arguments,result +this.each(function(){var $this=$(this) +var data=$this.data('oc.treelist') +var options=$.extend({},TreeListWidget.DEFAULTS,$this.data(),typeof option=='object'&&option) +if(!data)$this.data('oc.treelist',(data=new TreeListWidget(this,options))) +if(typeof option=='string')result=data[option].call(data) +if(typeof result!='undefined')return false}) +return result?result:this} +$.fn.treeListWidget.Constructor=TreeListWidget +$.fn.treeListWidget.noConflict=function(){$.fn.treeListWidget=old +return this} +$(document).render(function(){$('[data-control="treelist"]').treeListWidget();})}(window.jQuery);+function($){"use strict";var SidenavTree=function(element,options){this.options=options +this.$el=$(element) +this.init()} +SidenavTree.DEFAULTS={treeName:'sidenav_tree'} +SidenavTree.prototype.init=function(){var self=this +$(document.body).addClass('has-sidenav-tree') +this.statusCookieName=this.options.treeName+'groupStatus' +this.searchCookieName=this.options.treeName+'search' +this.$searchInput=$(this.options.searchInput) +this.$el.on('click','li > div.group',function(){self.toggleGroup($(this).closest('li')) +return false}) +this.$searchInput.on('input',function(){self.handleSearchChange()}) +var searchTerm=$.cookie(this.searchCookieName) +if(searchTerm!==undefined&&searchTerm.length>0){this.$searchInput.val(searchTerm) +this.applySearch()}var scrollbar=$('[data-control=scrollbar]',this.$el).data('oc.scrollbar'),active=$('li.active',this.$el) +if(active.length>0){scrollbar.gotoElement(active)}} +SidenavTree.prototype.toggleGroup=function(group){var $group=$(group),status=$group.attr('data-status') +status===undefined||status=='expanded'?this.collapseGroup($group):this.expandGroup($group)} +SidenavTree.prototype.collapseGroup=function(group){var $list=$('> ul',group),self=this +$list.css('overflow','hidden') +$list.animate({'height':0},{duration:100,queue:false,complete:function(){$list.css({'overflow':'visible','display':'none'}) +$(group).attr('data-status','collapsed') +$(window).trigger('oc.updateUi') +self.saveGroupStatus($(group).data('group-code'),true)}})} +SidenavTree.prototype.expandGroup=function(group,duration){var $list=$('> ul',group),self=this +duration=duration===undefined?100:duration +$list.css({'overflow':'hidden','height':0}) +$list.animate({'height':$list[0].scrollHeight},{duration:duration,queue:false,complete:function(){$list.css({'overflow':'visible','height':'auto','display':''}) +$(group).attr('data-status','expanded') +$(window).trigger('oc.updateUi') +self.saveGroupStatus($(group).data('group-code'),false)}})} +SidenavTree.prototype.saveGroupStatus=function(groupCode,collapsed){var collapsedGroups=$.cookie(this.statusCookieName),updatedGroups=[] +if(collapsedGroups===undefined){collapsedGroups=''}collapsedGroups=collapsedGroups.split('|') +$.each(collapsedGroups,function(){if(groupCode!=this)updatedGroups.push(this)}) +if(collapsed){updatedGroups.push(groupCode)}$.cookie(this.statusCookieName,updatedGroups.join('|'),{expires:30,path:'/'})} +SidenavTree.prototype.handleSearchChange=function(){var lastValue=this.$searchInput.data('oc.lastvalue');if(lastValue!==undefined&&lastValue==this.$searchInput.val()){return}this.$searchInput.data('oc.lastvalue',this.$searchInput.val()) +if(this.dataTrackInputTimer!==undefined){window.clearTimeout(this.dataTrackInputTimer)}var self=this +this.dataTrackInputTimer=window.setTimeout(function(){self.applySearch()},300);$.cookie(this.searchCookieName,$.trim(this.$searchInput.val()),{expires:30,path:'/'})} +SidenavTree.prototype.applySearch=function(){var query=$.trim(this.$searchInput.val()),words=query.toLowerCase().split(' '),visibleGroups=[],visibleItems=[],self=this +if(query.length==0){$('li',this.$el).removeClass('hidden') +return}$('ul.top-level > li',this.$el).each(function(){var $li=$(this) +if(self.textContainsWords($('div.group h3',$li).text(),words)){visibleGroups.push($li.get(0)) +$('ul li',$li).each(function(){visibleItems.push(this)})}else{$('ul li',$li).each(function(){if(self.textContainsWords($(this).text(),words)||self.textContainsWords($(this).data('keywords'),words)){visibleGroups.push($li.get(0)) +visibleItems.push(this)}})}}) +$('ul.top-level > li',this.$el).each(function(){var $li=$(this),groupIsVisible=$.inArray(this,visibleGroups)!==-1 +$li.toggleClass('hidden',!groupIsVisible) +if(groupIsVisible)self.expandGroup($li,0) +$('ul li',$li).each(function(){var $itemLi=$(this) +$itemLi.toggleClass('hidden',$.inArray(this,visibleItems)==-1)})}) +return false} +SidenavTree.prototype.textContainsWords=function(text,words){text=text.toLowerCase() +for(var i=0;i':'>','"':'"',"'":''','/':'/'},htmlEscaper=/[&<>"'\/]/g +return(''+string).replace(htmlEscaper,function(match){return htmlEscapes[match];})} +if(!!window.MSInputMethodContext&&!!document.documentMode){$(window).on('resize',function(){fixMediaManager() +fixSidebar()}) +function fixMediaManager(){var $el=$('div[data-control="media-manager"] .control-scrollpad') +$el.height($el.parent().height())}function fixSidebar(){$('#layout-sidenav').height(Math.max($('#layout-body').innerHeight(),$(window).height()-$('#layout-mainmenu').height()))}} \ No newline at end of file diff --git a/modules/backend/assets/js/winter.alert.js b/modules/backend/assets/js/winter.alert.js new file mode 100644 index 0000000..6a3558d --- /dev/null +++ b/modules/backend/assets/js/winter.alert.js @@ -0,0 +1,92 @@ +/* + * Alerts + * + * Displays alert and confirmation dialogs + * + * JavaScript API: + * $.wn.alert() + * $.wn.confirm() + * + * Dependences: + * - Sweet Alert + * - Translations (winter.lang.js) + */ +(function($){ + + if ($.wn === undefined) + $.wn = {} + if ($.oc === undefined) + $.oc = $.wn + + $.wn.alert = function alert(message) { + swal({ + title: message, + confirmButtonClass: 'btn-primary' + }) + } + + $.wn.confirm = function confirm(message, callback) { + + swal({ + title: message, + showCancelButton: true, + confirmButtonClass: 'btn-primary' + }, callback) + + } + +})(jQuery); + +/* + * Implement alerts with AJAX framework + */ + +$(window).on('ajaxErrorMessage', function(event, message){ + if (!message) return + + $.wn.alert(message) + + // Prevent the default alert() message + event.preventDefault() +}) + +$(window).on('ajaxConfirmMessage', function(event, message){ + if (!message) return + + $.wn.confirm(message, function(isConfirm){ + isConfirm + ? event.promise.resolve() + : event.promise.reject() + }) + + // Prevent the default confirm() message + event.preventDefault() + return true +}) + +/* + * Override "Sweet Alert" functions to translate default buttons + */ + +$(document).ready(function(){ + if (!window.swal) return + + var swal = window.swal + + window.sweetAlert = window.swal = function(message, callback) { + if (typeof message === 'object') { + // Do not override if texts are provided + message.confirmButtonText = message.confirmButtonText || $.wn.lang.get('alert.confirm_button_text') + message.cancelButtonText = message.cancelButtonText || $.wn.lang.get('alert.cancel_button_text') + } + else { + message = { + title: message, + confirmButtonText: $.wn.lang.get('alert.confirm_button_text'), + cancelButtonText: $.wn.lang.get('alert.cancel_button_text') + } + } + + swal(message, callback) + } +}) diff --git a/modules/backend/assets/js/winter.datetime.js b/modules/backend/assets/js/winter.datetime.js new file mode 100644 index 0000000..8bab57a --- /dev/null +++ b/modules/backend/assets/js/winter.datetime.js @@ -0,0 +1,175 @@ +/* + * Date time converter. + * See moment.js for format options. + * http://momentjs.com/docs/#/displaying/format/ + * + * Usage: + * + * + * + * Alias options: + * + * time -> 6:28 AM + * timeLong -> 6:28:01 AM + * date -> 04/23/2016 + * dateMin -> 4/23/2016 + * dateLong -> April 23, 2016 + * dateLongMin -> Apr 23, 2016 + * dateTime -> April 23, 2016 6:28 AM + * dateTimeMin -> Apr 23, 2016 6:28 AM + * dateTimeLong -> Saturday, April 23, 2016 6:28 AM + * dateTimeLongMin -> Sat, Apr 23, 2016 6:29 AM + * + */ ++function ($) { "use strict"; + var Base = $.wn.foundation.base, + BaseProto = Base.prototype + + var DateTimeConverter = function (element, options) { + this.$el = $(element) + this.options = options || {} + + $.wn.foundation.controlUtils.markDisposable(element) + Base.call(this) + this.init() + } + + DateTimeConverter.prototype = Object.create(BaseProto) + DateTimeConverter.prototype.constructor = DateTimeConverter + + DateTimeConverter.prototype.init = function() { + this.initDefaults() + + this.$el.text(this.getDateTimeValue()) + + this.$el.one('dispose-control', this.proxy(this.dispose)) + } + + DateTimeConverter.prototype.initDefaults = function() { + if (!this.options.timezone) { + this.options.timezone = $('meta[name="backend-timezone"]').attr('content') + } + + if (!this.options.locale) { + this.options.locale = $('meta[name="backend-locale"]').attr('content') + } + + if (!this.options.format) { + this.options.format = 'llll' + } + + if (this.options.formatAlias) { + this.options.format = this.getFormatFromAlias(this.options.formatAlias) + } + + this.appTimezone = $('meta[name="app-timezone"]').attr('content') + if (!this.appTimezone) { + this.appTimezone = 'UTC' + } + } + + DateTimeConverter.prototype.getDateTimeValue = function() { + this.datetime = this.$el.attr('datetime') + + if (this.$el.get(0).hasAttribute('data-ignore-timezone')) { + this.appTimezone = 'UTC' + this.options.timezone = 'UTC' + } + + var momentObj = moment.tz(this.datetime, this.appTimezone), + result + + if (this.options.locale) { + momentObj = momentObj.locale(this.options.locale) + } + + if (this.options.timezone) { + momentObj = momentObj.tz(this.options.timezone) + } + + if (this.options.timeSince) { + result = momentObj.fromNow() + } + else if (this.options.timeTense) { + result = momentObj.calendar() + } + else { + result = momentObj.format(this.options.format) + } + + return result + } + + DateTimeConverter.prototype.getFormatFromAlias = function(alias) { + var map = { + time: 'LT', + timeLong: 'LTS', + date: 'L', + dateMin: 'l', + dateLong: 'LL', + dateLongMin: 'll', + dateTime: 'LLL', + dateTimeMin: 'lll', + dateTimeLong: 'LLLL', + dateTimeLongMin: 'llll' + } + + return map[alias] ? map[alias] : 'llll' + } + + DateTimeConverter.prototype.dispose = function() { + this.$el.off('dispose-control', this.proxy(this.dispose)) + this.$el.removeData('oc.dateTimeConverter') + + this.$el = null + this.options = null + + BaseProto.dispose.call(this) + } + + DateTimeConverter.DEFAULTS = { + format: null, + formatAlias: null, + timezone: null, + locale: null, + timeTense: false, + timeSince: false + } + + // PLUGIN DEFINITION + // ============================ + + var old = $.fn.dateTimeConverter + + $.fn.dateTimeConverter = function (option) { + var args = Array.prototype.slice.call(arguments, 1), items, result + + items = this.each(function () { + var $this = $(this) + var data = $this.data('oc.dateTimeConverter') + var options = $.extend({}, DateTimeConverter.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.dateTimeConverter', (data = new DateTimeConverter(this, options))) + if (typeof option == 'string') result = data[option].apply(data, args) + if (typeof result != 'undefined') return false + }) + + return result ? result : items + } + + $.fn.dateTimeConverter.Constructor = DateTimeConverter + + $.fn.dateTimeConverter.noConflict = function () { + $.fn.dateTimeConverter = old + return this + } + + $(document).render(function (){ + $('time[data-datetime-control]').dateTimeConverter() + }) + +}(window.jQuery); diff --git a/modules/backend/assets/js/winter.filelist.js b/modules/backend/assets/js/winter.filelist.js new file mode 100644 index 0000000..9796372 --- /dev/null +++ b/modules/backend/assets/js/winter.filelist.js @@ -0,0 +1,169 @@ +/* + * File List + * + * Creates a tree list of clickable folders and files. + * + * Data attributes: + * - data-control="filelist" - enables the file list plugin + * - data-group-status-handler - AJAX handler to execute when a group is collapsed or expanded by a user + * + * JavaScript API: + * $('#list').fileList() + * + * Events + * - open.oc.list - this event is triggered on the list element when an item is clicked. + * + * Dependences: + * - Null + */ + ++function ($) { "use strict"; + + // FILELIST CLASS DEFINITION + // ============================ + + var FileList = function(element, options) { + this.options = options + this.$el = $(element) + + this.init(); + } + + FileList.DEFAULTS = { + ignoreItemClick: false + } + + FileList.prototype.init = function (){ + var self = this + + this.$el.on('click', 'li.group > h4 > a, li.group > div.group', function() { + self.toggleGroup($(this).closest('li')) + + return false; + }); + + if (!this.options.ignoreItemClick) { + this.$el.on('click', 'li.item > a', function(event) { + var e = $.Event('open.oc.list', {relatedTarget: $(this).parent().get(0), clickEvent: event}) + self.$el.trigger(e, this) + + return false + }) + } + + this.$el.on('ajaxUpdate', $.proxy(this.update, this)) + } + + FileList.prototype.toggleGroup = function(group) { + var $group = $(group); + + $group.attr('data-status') == 'expanded' ? + this.collapseGroup($group) : + this.expandGroup($group) + } + + FileList.prototype.collapseGroup = function(group) { + var + $list = $('> ul, > div.subitems', group), + self = this; + + $list.css('overflow', 'hidden') + $list.animate({'height': 0}, { duration: 100, queue: false, complete: function() { + $list.css({ + 'overflow': 'visible', + 'display': 'none' + }) + $(group).attr('data-status', 'collapsed') + $(window).trigger('resize') + } }) + + this.sendGroupStatusRequest(group, 0); + } + + FileList.prototype.expandGroup = function(group) { + var + $list = $('> ul, > div.subitems', group), + self = this; + + $list.css({ + 'overflow': 'hidden', + 'display': 'block', + 'height': 0 + }) + $list.animate({'height': $list[0].scrollHeight}, { duration: 100, queue: false, complete: function() { + $list.css({ + 'overflow': 'visible', + 'height': 'auto' + }) + $(group).attr('data-status', 'expanded') + $(window).trigger('resize') + } }) + + this.sendGroupStatusRequest(group, 1); + } + + FileList.prototype.sendGroupStatusRequest = function(group, status) { + if (this.options.groupStatusHandler !== undefined) { + var groupId = $(group).data('group-id') + if (groupId === undefined) + groupId = $('> h4 a', group).text(); + + $(group).request(this.options.groupStatusHandler, {data: {group: groupId, status: status}}) + } + } + + FileList.prototype.markActive = function(dataId) { + $('li.item', this.$el).removeClass('active') + if (dataId) + $('li.item[data-id="'+dataId+'"]', this.$el).addClass('active') + + this.dataId = dataId + } + + FileList.prototype.update = function() { + if (this.dataId !== undefined) + this.markActive(this.dataId) + } + + // FILELIST PLUGIN DEFINITION + // ============================ + + var old = $.fn.fileList + + $.fn.fileList = function (option) { + var args = arguments; + + return this.each(function () { + var $this = $(this) + var data = $this.data('oc.fileList') + var options = $.extend({}, FileList.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data) $this.data('oc.fileList', (data = new FileList(this, options))) + if (typeof option == 'string') { + var methodArgs = []; + for (var i=1; i .layout-cell'), + $flyout = this.$el.find('> .flyout') + + $('[data-control=layout-sidepanel]').sidePanelTab('hideSidePanel') + + this.removeOverlay() + + for (var i = 0; i < $cells.length; i++) { + var $cell = $($cells[i]), + width = $cell.width() + + $cell.css('width', width) + } + + this.createOverlay() + + window.setTimeout(this.proxy(this.setBodyClass), 1) + $flyout.css('width', this.options.flyoutWidth) + + this.hideToggle() + } + + Flyout.prototype.hide = function() { + var $cells = this.$el.find('> .layout-cell'), + $flyout = this.$el.find('> .flyout') + + for (var i = 0; i < $cells.length; i++) { + var $cell = $($cells[i]) + + $cell.css('width', '') + } + + $flyout.css('width', 0) + + window.setTimeout(this.proxy(this.removeBodyClass), 1) + window.setTimeout(this.proxy(this.removeOverlayAndShowToggle), 300) + } + + // FLYOUT INTERNAL METHODS + // ============================ + + Flyout.prototype.init = function() { + this.build() + } + + Flyout.prototype.build = function() { + if (this.options.flyoutToggle) { + this.buildToggle() + } + } + + Flyout.prototype.buildToggle = function() { + var $toggleContainer = $(this.options.flyoutToggle), + $toggle = $('
') + + $toggle.on('click', this.proxy(this.show)) + $toggleContainer.append($toggle) + } + + Flyout.prototype.removeToggle = function() { + var $toggle = this.getToggle() + + $toggle.off('click', this.proxy(this.show)) + $toggle.remove() + } + + Flyout.prototype.hideToggle = function() { + if (!this.options.flyoutToggle) { + return + } + + this.getToggle().hide() + } + + Flyout.prototype.showToggle = function() { + if (!this.options.flyoutToggle) { + return + } + + this.getToggle().show() + } + + Flyout.prototype.getToggle = function() { + var $toggleContainer = $(this.options.flyoutToggle) + + return $toggleContainer.find('.flyout-toggle') + } + + Flyout.prototype.setBodyClass = function() { + $(document.body).addClass('flyout-visible') + } + + Flyout.prototype.removeBodyClass = function() { + $(document.body).removeClass('flyout-visible') + } + + Flyout.prototype.createOverlay = function() { + this.$overlay = $('
') + + var position = this.$el.offset() + + this.$overlay.css({ + top: position.top, + left: this.options.flyoutWidth + }) + + this.$overlay.on('click', this.proxy(this.onOverlayClick)) + $(document.body).on('keydown', this.proxy(this.onDocumentKeydown)) + + $(document.body).append(this.$overlay) + } + + Flyout.prototype.removeOverlay = function() { + if (!this.$overlay) { + return + } + + this.$overlay.off('click', this.proxy(this.onOverlayClick)) + $(document.body).off('keydown', this.proxy(this.onDocumentKeydown)) + + this.$overlay.remove() + this.$overlay = null + } + + Flyout.prototype.removeOverlayAndShowToggle = function() { + this.removeOverlay() + this.showToggle() + } + + // EVENT HANDLERS + // ============================ + + Flyout.prototype.onOverlayClick = function() { + this.hide() + } + + Flyout.prototype.onDocumentKeydown = function(ev) { + if (ev.key === 'Escape') { + this.hide(); + } + } + + // FLYOUT PLUGIN DEFINITION + // ============================ + + Flyout.DEFAULTS = { + flyoutWidth: 400, + flyoutToggle: null + } + + var old = $.fn.flyout + + $.fn.flyout = function (option) { + var args = Array.prototype.slice.call(arguments, 1), + result = undefined + + this.each(function () { + var $this = $(this) + var data = $this.data('oc.flyout') + var options = $.extend({}, Flyout.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.flyout', (data = new Flyout(this, options))) + if (typeof option == 'string') result = data[option].apply(data, args) + if (typeof result != 'undefined') return false + }) + + return result ? result : this + } + + $.fn.flyout.Constructor = Flyout + + // FLYOUT NO CONFLICT + // ================= + + $.fn.flyout.noConflict = function () { + $.fn.flyout = old + return this + } + + // FLYOUT DATA-API + // =============== + + // Currently flyouts don't use the document render event + // and can't be created dynamically (performance considerations). + $(document).ready(function(){ + $('div[data-control=flyout]').flyout() + }) +}(window.jQuery); \ No newline at end of file diff --git a/modules/backend/assets/js/winter.js b/modules/backend/assets/js/winter.js new file mode 100644 index 0000000..f05a4bc --- /dev/null +++ b/modules/backend/assets/js/winter.js @@ -0,0 +1,35 @@ +/* + * This is a bundle file, you can compile this by running + * + * php artisan winter:util compile assets + * + * @see winter-min.js + * + +=require vendor/jquery.touchwipe.js +=require vendor/jquery.autoellipsis.js +=require vendor/jquery.waterfall.js +=require vendor/jquery.cookie.js +=require ../vendor/dropzone/dropzone.js +=require ../vendor/sweet-alert/sweet-alert.js +=require ../vendor/jcrop/js/jquery.Jcrop.js +=require ../../../system/assets/vendor/prettify/prettify.js +=require ../../widgets/mediamanager/assets/js/mediamanager-global.js + +=require winter.lang.js +=require winter.alert.js +=require winter.scrollpad.js +=require winter.verticalmenu.js +=require winter.navbar.js +=require winter.sidenav.js +=require winter.scrollbar.js +=require winter.filelist.js +=require winter.layout.js +=require winter.sidepaneltab.js +=require winter.simplelist.js +=require winter.treelist.js +=require winter.sidenav-tree.js +=require winter.datetime.js + +=require backend.js +*/ diff --git a/modules/backend/assets/js/winter.lang.js b/modules/backend/assets/js/winter.lang.js new file mode 100644 index 0000000..cefd146 --- /dev/null +++ b/modules/backend/assets/js/winter.lang.js @@ -0,0 +1,52 @@ +/* + * Client side translations + */ + +if ($.wn === undefined) + $.wn = {} +if ($.oc === undefined) + $.oc = $.wn + +if ($.wn.langMessages === undefined) + $.wn.langMessages = {} + +$.wn.lang = (function(lang, messages) { + + lang.load = function(locale) { + if (messages[locale] === undefined) { + messages[locale] = {} + } + + lang.loadedMessages = messages[locale] + } + + lang.get = function(name, defaultValue) { + if (!name) return + + var result = lang.loadedMessages + + if (!defaultValue) defaultValue = name + + $.each(name.split('.'), function(index, value) { + if (result[value] === undefined) { + result = defaultValue + return false + } + + result = result[value] + }) + + return result + } + + if (lang.locale === undefined) { + lang.locale = $('html').attr('lang') || 'en' + } + + if (lang.loadedMessages === undefined) { + lang.load(lang.locale) + } + + return lang + +})($.wn.lang || {}, $.wn.langMessages); \ No newline at end of file diff --git a/modules/backend/assets/js/winter.layout.js b/modules/backend/assets/js/winter.layout.js new file mode 100644 index 0000000..d2276c7 --- /dev/null +++ b/modules/backend/assets/js/winter.layout.js @@ -0,0 +1,86 @@ +(function($){ + var WinterLayout = function() { + this.$accountMenuOverlay = null + } + + WinterLayout.prototype.setPageTitle = function(title) { + var $title = $('title') + + if (this.pageTitleTemplate === undefined) + this.pageTitleTemplate = $title.data('titleTemplate') + + $title.text(this.pageTitleTemplate.replace('%s', title)) + } + + WinterLayout.prototype.updateLayout = function(title) { + var $children, $el, fixedWidth, margin + + $('[data-calculate-width]').each(function(){ + $children = $(this).children() + + if ($children.length > 0) { + fixedWidth = 0 + + $children.each(function() { + $el = $(this) + margin = $el.data('oc.layoutMargin') + + if (margin === undefined) { + margin = parseInt($el.css('marginRight')) + parseInt($el.css('marginLeft')) + $el.data('oc.layoutMargin', margin) + } + fixedWidth += $el.get(0).offsetWidth + margin + }) + + $(this).width(fixedWidth) + $(this).trigger('oc.widthFixed') + } + }) + } + + WinterLayout.prototype.toggleAccountMenu = function(el) { + var self = this, + $el = $(el), + $parent = $(el).parent(), + $menu = $el.next() + + $el.tooltip('hide') + + if ($menu.hasClass('active')) { + self.$accountMenuOverlay.remove() + $parent.removeClass('highlight') + $menu.removeClass('active') + } + else { + self.$accountMenuOverlay = $('
').addClass('popover-overlay') + $(document.body).append(self.$accountMenuOverlay) + $parent.addClass('highlight') + $menu.addClass('active') + + self.$accountMenuOverlay.one('click', function(){ + self.$accountMenuOverlay.remove() + $menu.removeClass('active') + $parent.removeClass('highlight') + }) + } + } + + if ($.wn === undefined) + $.wn = {} + if ($.oc === undefined) + $.oc = $.wn + + $.wn.layout = new WinterLayout() + + $(document).ready(function(){ + $.wn.layout.updateLayout() + + window.setTimeout($.wn.layout.updateLayout, 100) + }) + $(window).on('resize', function() { + $.wn.layout.updateLayout() + }) + $(window).on('oc.updateUi', function() { + $.wn.layout.updateLayout() + }) +})(jQuery); \ No newline at end of file diff --git a/modules/backend/assets/js/winter.navbar.js b/modules/backend/assets/js/winter.navbar.js new file mode 100644 index 0000000..37c1cde --- /dev/null +++ b/modules/backend/assets/js/winter.navbar.js @@ -0,0 +1,41 @@ +/* + * Top navigation bar. Features of the bar: + * - Hide content if the display width is less than 768px. In this case the menu icon is displayed. + * When the icon is clicked, the menu content is displayed on the left side of the page. + * - If the content doesn't fit the navbar, it can be dragged left and right. + * + * Dependences: + * - DragScroll (winter.dragscroll.js) + * - VerticalMenu (winter.verticalmenu.js) + */ + +(function($){ + $(document).ready(function(){ + $('nav.navbar').each(function(){ + var + navbar = $(this), + nav = $('ul.nav', navbar), + collapseMode = navbar.hasClass('navbar-mode-collapse'), + isMobile = $('html').hasClass('mobile') + + nav.verticalMenu($('a.menu-toggle', navbar), { + breakpoint: collapseMode ? Infinity : 769 + }) + + $('li.with-tooltip:not(.active) > a', navbar).tooltip({ + container: 'body', + placement: 'bottom', + template: '' + }) + .on('show.bs.tooltip', function (e) { + if (isMobile) e.preventDefault() + }) + + // Scroll to the currently active nav item. + var dragScroll = $('[data-control=toolbar]', navbar).data('oc.dragScroll') + if (dragScroll) { + dragScroll.goToElement($('ul.nav > li.active', navbar), undefined, {'duration': 0}) + } + }) + }) +})(jQuery); diff --git a/modules/backend/assets/js/winter.scrollbar.js b/modules/backend/assets/js/winter.scrollbar.js new file mode 100644 index 0000000..39b6e11 --- /dev/null +++ b/modules/backend/assets/js/winter.scrollbar.js @@ -0,0 +1,409 @@ +/* + * Creates a scrollbar in a container. + * + * Note the element must have a height set for vertical, + * and a width set for horizontal. + * + * Data attributes: + * - data-control="scrollbar" - enables the scrollbar plugin + * + * JavaScript API: + * $('#area').scrollbar() + * + * Dependences: + * - Mouse Wheel plugin (mousewheel.js) + */ ++function ($) { "use strict"; + var Base = $.wn.foundation.base, + BaseProto = Base.prototype + + var Scrollbar = function (element, options) { + + var + $el = this.$el = $(element), + el = $el.get(0), + self = this, + options = this.options = options || {}, + sizeName = this.sizeName = options.vertical ? 'height' : 'width', + isNative = $('html').hasClass('mobile'), + isTouch = this.isTouch = Modernizr.touchevents, + isScrollable = this.isScrollable = false, + isLocked = this.isLocked = false, + eventElementName = options.vertical ? 'pageY' : 'pageX', + dragStart = 0, + startOffset = 0; + + $.wn.foundation.controlUtils.markDisposable(element) + + Base.call(this) + + this.$el.one('dispose-control', this.proxy(this.dispose)) + + /* + * Native (mobile) environments use overflow auto in CSS + */ + if (isNative) { + return + } + + /* + * Create Scrollbar + */ + this.$scrollbar = $('
').addClass('scrollbar-scrollbar') + this.$track = $('
').addClass('scrollbar-track').appendTo(this.$scrollbar) + this.$thumb = $('
').addClass('scrollbar-thumb').appendTo(this.$track) + + $el + .addClass('drag-scrollbar') + .addClass(options.vertical ? 'vertical' : 'horizontal') + .prepend(this.$scrollbar) + + /* + * Bind events + */ + if (isTouch) { + this.$el.on('touchstart', function (event){ + var touchEvent = event.originalEvent; + if (touchEvent.touches.length == 1) { + startDrag(touchEvent.touches[0]) + event.stopPropagation() + } + }) + } + else { + this.$thumb.on('mousedown', function (event){ + startDrag(event) + }) + this.$track.on('mouseup', function (event){ + moveDrag(event) + }) + } + + $el.mousewheel(function (event){ + var offset = self.options.vertical + ? ((event.deltaFactor * event.deltaY) * -1) + : (event.deltaFactor * event.deltaX) + + return !scrollWheel(offset * self.options.scrollSpeed) + }) + + $el.on('oc.scrollbar.gotoStart', function(event){ + self.options.vertical + ? $el.scrollTop(0) + : $el.scrollLeft(0) + + self.update() + event.stopPropagation() + }) + + $(window).on('resize', $.proxy(this.update, this)) + $(window).on('oc.updateUi', $.proxy(this.update, this)) + + /* + * Internal event, drag has started + */ + function startDrag(event) { + $('body').addClass('drag-noselect') + $el.trigger('oc.scrollStart') + + dragStart = event[eventElementName] + startOffset = self.options.vertical ? $el.scrollTop() : $el.scrollLeft() + + if (isTouch) { + $(window).on('touchmove.scrollbar', function(event) { + var touchEvent = event.originalEvent + if (moveDrag(touchEvent.touches[0])) + event.preventDefault(); + }); + + $el.on('touchend.scrollbar', stopDrag) + } + else { + $(window).on('mousemove.scrollbar', function(event){ + moveDrag(event) + return false + }) + + $(window).on('mouseup.scrollbar', function(){ + stopDrag() + return false + }) + } + } + + /* + * Internal event, drag is active + */ + function moveDrag(event) { + self.isLocked = true; + + var + offset, + dragTo = event[eventElementName] + + // Touch devices use an inverse scrolling interface + // with a 1:1 ratio + if (self.isTouch) { + offset = dragStart - dragTo + } + // Mouse devices use a natural scrolling interface + // with a track:canvas ratio + else { + var ratio = self.getCanvasSize() / self.getViewportSize() + offset = (dragTo - dragStart) * ratio + } + + self.options.vertical + ? $el.scrollTop(startOffset + offset) + : $el.scrollLeft(startOffset + offset) + + self.setThumbPosition() + + return self.options.vertical + ? el.scrollTop != startOffset + : el.scrollLeft != startOffset + } + + /* + * Internal event, drag has ended + */ + function stopDrag() { + $('body').removeClass('drag-noselect') + $el.trigger('oc.scrollEnd') + + $(window).off('.scrollbar') + } + + /* + * Scroll wheel has moved by supplied offset + */ + + var isWebkit = $(document.documentElement).hasClass('webkit') + + function scrollWheel(offset) { + startOffset = self.options.vertical ? el.scrollTop : el.scrollLeft + $el.trigger('oc.scrollStart') + + self.options.vertical + ? $el.scrollTop(startOffset + offset) + : $el.scrollLeft(startOffset + offset) + + var scrolled = self.options.vertical + ? el.scrollTop != startOffset + : el.scrollLeft != startOffset + + self.setThumbPosition() + if (!isWebkit) { + if (self.endScrollTimeout !== undefined) { + clearTimeout(self.endScrollTimeout) + self.endScrollTimeout = undefined + } + + self.endScrollTimeout = setTimeout(function() { + $el.trigger('oc.scrollEnd') + self.endScrollTimeout = undefined + }, 50) + } else { + $el.trigger('oc.scrollEnd') + } + + return scrolled + } + + /* + * Give the DOM a second, then set the track and thumb size + */ + setTimeout(function() { self.update() }, 1); + } + + Scrollbar.prototype = Object.create(BaseProto) + Scrollbar.prototype.constructor = Scrollbar + + Scrollbar.prototype.dispose = function() { + this.unregisterHandlers() + + BaseProto.dispose.call(this) + } + + Scrollbar.prototype.unregisterHandlers = function() { + + } + + Scrollbar.DEFAULTS = { + vertical: true, + scrollSpeed: 2, + animation: true, + start: function() {}, + drag: function() {}, + stop: function() {} + } + + Scrollbar.prototype.update = function() { + if (!this.$scrollbar) + return + + this.$scrollbar.hide() + this.setThumbSize() + this.setThumbPosition() + this.$scrollbar.show() + } + + Scrollbar.prototype.setThumbSize = function() { + var properties = this.calculateProperties() + + this.isScrollable = !(properties.thumbSizeRatio >= 1); + this.$scrollbar.toggleClass('disabled', !this.isScrollable) + + if (this.options.vertical) { + this.$track.height(properties.canvasSize) + this.$thumb.height(properties.thumbSize) + } + else { + this.$track.width(properties.canvasSize) + this.$thumb.width(properties.thumbSize) + } + } + + Scrollbar.prototype.setThumbPosition = function() { + var properties = this.calculateProperties() + + if (this.options.vertical) + this.$thumb.css({top: properties.thumbPosition}) + else + this.$thumb.css({left: properties.thumbPosition}) + } + + Scrollbar.prototype.calculateProperties = function() { + + var $el = this.$el, + properties = {}; + + properties.viewportSize = this.getViewportSize() + properties.canvasSize = this.getCanvasSize() + properties.scrollAmount = (this.options.vertical) ? $el.scrollTop() : $el.scrollLeft() + + properties.thumbSizeRatio = properties.viewportSize / properties.canvasSize + properties.thumbSize = properties.viewportSize * properties.thumbSizeRatio + + properties.thumbPositionRatio = properties.scrollAmount / (properties.canvasSize - properties.viewportSize) + properties.thumbPosition = ((properties.viewportSize - properties.thumbSize) * properties.thumbPositionRatio) + properties.scrollAmount + + if (isNaN(properties.thumbPosition)) + properties.thumbPosition = 0 + + return properties; + } + + Scrollbar.prototype.getViewportSize = function() { + return (this.options.vertical) + ? this.$el.height() + : this.$el.width(); + } + + Scrollbar.prototype.getCanvasSize = function() { + return (this.options.vertical) + ? this.$el.get(0).scrollHeight + : this.$el.get(0).scrollWidth; + } + + Scrollbar.prototype.gotoElement = function(element, callback) { + var $el = $(element) + if (!$el.length) + return; + + var self = this, + offset = 0, + animated = false, + params = { + duration: 300, + queue: false, + complete: function(){ + if (callback !== undefined) + callback() + } + } + + if (!this.options.vertical) { + offset = $el.get(0).offsetLeft - this.$el.scrollLeft() + + if (offset < 0) { + this.$el.animate({'scrollLeft': $el.get(0).offsetLeft}, params) + animated = true + } else { + offset = $el.get(0).offsetLeft + $el.outerWidth() - (this.$el.scrollLeft() + this.$el.outerWidth()) + if (offset > 0) { + this.$el.animate({'scrollLeft': $el.get(0).offsetLeft + $el.outerWidth() - this.$el.outerWidth()}, params) + animated = true + } + } + } else { + offset = $el.get(0).offsetTop - this.$el.scrollTop() + + if (this.options.animation) { + if (offset < 0) { + this.$el.animate({'scrollTop': $el.get(0).offsetTop}, params) + animated = true + } else { + offset = $el.get(0).offsetTop - (this.$el.scrollTop() + this.$el.outerHeight()) + if (offset > 0) { + this.$el.animate({'scrollTop': $el.get(0).offsetTop + $el.outerHeight() - this.$el.outerHeight()}, params) + animated = true + } + } + } else { + if (offset < 0) { + this.$el.scrollTop($el.get(0).offsetTop) + } else { + offset = $el.get(0).offsetTop - (this.$el.scrollTop() + this.$el.outerHeight()) + if (offset > 0) + this.$el.scrollTop($el.get(0).offsetTop + $el.outerHeight() - this.$el.outerHeight()) + } + } + } + + if (!animated && callback !== undefined) + callback() + + return this + } + + Scrollbar.prototype.dispose = function() { + this.$el = null + this.$scrollbar = null + this.$track = null + this.$thumb = null + } + + // SCROLLBAR PLUGIN DEFINITION + // ============================ + + var old = $.fn.scrollbar + + $.fn.scrollbar = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('oc.scrollbar') + var options = $.extend({}, Scrollbar.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data) $this.data('oc.scrollbar', (data = new Scrollbar(this, options))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.scrollbar.Constructor = Scrollbar + + // SCROLLBAR NO CONFLICT + // ================= + + $.fn.scrollbar.noConflict = function () { + $.fn.scrollbar = old + return this + } + + // SCROLLBAR DATA-API + // =============== + $(document).render(function(){ + $('[data-control=scrollbar]').scrollbar() + }) + +}(window.jQuery); \ No newline at end of file diff --git a/modules/backend/assets/js/winter.scrollpad.js b/modules/backend/assets/js/winter.scrollpad.js new file mode 100644 index 0000000..3935f24 --- /dev/null +++ b/modules/backend/assets/js/winter.scrollpad.js @@ -0,0 +1,310 @@ +/* + * ScrollPad plugin. + * + * This plugin creates a scrollable area with features similar (but more limited) + * to winter.scrollbar.js, with virtual scroll bars. This plugin is more lightweight + * in terms of calculations and more responsive. It doesn't use scripting for scrolling, + * instead it uses the native scrolling and listens for the onscroll event to update + * the virtual scroll bars. + * + * The plugin is partially based on Trackpad Scroll Emulator + * https://github.com/jnicol/trackpad-scroll-emulator, cleaned up for the better CPU and + * memory (DOM references) management. + * + * Expected markup: + *
+ *
+ *
+ * The content goes here. The two wrapping + * DIV elements are required. + *
+ *
+ *
+ * + * Data attributes: + * - data-control="scrollpad" - enables the plugin. + * - data-direction="vertical|horizontal" - sets the scrolling direction. + * + * JavaScript API: + * $('#area').scrollpad({direction: 'vertical'}) + * $('#area').scrollpad('dispose') + * $('#area').scrollpad('scrollToStart') + * + * TODO: In FireFox the control in the horizontal mode displays the native scrollbars, + * because negative margin-bottom in the scrollable element doesn't work for some reason. + * Try to align the scrollable element with absolute positioning (negative right and bottom) + * instead of negative margins. + * + */ ++function ($) { "use strict"; + + var Base = $.wn.foundation.base, + BaseProto = Base.prototype + + // SCROLLPAD CLASS DEFINITION + // ============================ + + var Scrollpad = function(element, options) { + this.$el = $(element) + this.scrollbarElement = null + this.dragHandleElement = null + this.scrollContentElement = null + this.contentElement = null + this.options = options + this.scrollbarSize = null + this.updateScrollbarTimer = null + this.dragOffset = null + + Base.call(this) + + // + // Initialization + // + + this.init() + + $.wn.foundation.controlUtils.markDisposable(element) + } + + Scrollpad.prototype = Object.create(BaseProto) + Scrollpad.prototype.constructor = Scrollpad + + Scrollpad.prototype.dispose = function() { + this.unregisterHandlers() + + this.$el.get(0).removeChild(this.scrollbarElement) + this.$el.removeData('oc.scrollpad') + this.$el = null + + this.scrollbarElement = null + this.dragHandleElement = null + this.scrollContentElement = null + this.contentElement = null + + BaseProto.dispose.call(this) + } + + Scrollpad.prototype.scrollToStart = function() { + var scrollAttr = this.options.direction == 'vertical' ? 'scrollTop' : 'scrollLeft' + this.scrollContentElement[scrollAttr] = 0 + } + + Scrollpad.prototype.update = function() { + this.updateScrollbarSize() + } + + // SCROLLPAD INTERNAL METHODS + // ============================ + + Scrollpad.prototype.init = function() { + this.build() + this.setScrollContentSize() + this.registerHandlers() + } + + Scrollpad.prototype.build = function() { + var el = this.$el.get(0) + + this.scrollContentElement = el.children[0] + this.contentElement = this.scrollContentElement.children[0] + this.$el.prepend('
') + this.scrollbarElement = el.querySelector('.scrollpad-scrollbar') + this.dragHandleElement = el.querySelector('.scrollpad-scrollbar > .drag-handle') + } + + Scrollpad.prototype.registerHandlers = function() { + this.$el.on('mouseenter', this.proxy(this.onMouseEnter)) + this.$el.on('mouseleave', this.proxy(this.onMouseLeave)) + + this.$el.one('dispose-control', this.proxy(this.dispose)) + + this.scrollContentElement.addEventListener('scroll', this.proxy(this.onScroll)) + this.dragHandleElement.addEventListener('mousedown', this.proxy(this.onStartDrag)) + } + + Scrollpad.prototype.unregisterHandlers = function() { + this.$el.off('mouseenter', this.proxy(this.onMouseEnter)) + this.$el.off('mouseleave', this.proxy(this.onMouseLeave)) + this.$el.off('dispose-control', this.proxy(this.dispose)) + this.scrollContentElement.removeEventListener('scroll', this.proxy(this.onScroll)) + this.dragHandleElement.removeEventListener('mousedown', this.proxy(this.onStartDrag)) + + document.removeEventListener('mousemove', this.proxy(this.onMouseMove)) + document.removeEventListener('mouseup', this.proxy(this.onEndDrag)) + } + + Scrollpad.prototype.setScrollContentSize = function() { + var scrollbarSize = this.getScrollbarSize() + + if (this.options.direction == 'vertical') + this.scrollContentElement.setAttribute('style', 'margin-right: -' + scrollbarSize + 'px') + else + this.scrollContentElement.setAttribute('style', 'margin-bottom: -' + scrollbarSize + 'px') + } + + Scrollpad.prototype.getScrollbarSize = function() { + if (this.scrollbarSize !== null) + return this.scrollbarSize + + var testerElement = document.createElement('div') + testerElement.setAttribute('class', 'scrollpad-scrollbar-size-tester') + testerElement.appendChild(document.createElement('div')) + + document.body.appendChild(testerElement) + + var width = testerElement.offsetWidth, + innerWidth = testerElement.querySelector('div').offsetWidth + + document.body.removeChild(testerElement) + + // Some magic for FireFox, see + // https://github.com/jnicol/trackpad-scroll-emulator/blob/master/jquery.trackpad-scroll-emulator.js + if (width === innerWidth && navigator.userAgent.toLowerCase().indexOf('firefox') > -1) + return this.scrollbarSize = 17 + + return this.scrollbarSize = width - innerWidth + } + + Scrollpad.prototype.updateScrollbarSize = function() { + this.scrollbarElement.removeAttribute('data-hidden') + + var contentSize = this.options.direction == 'vertical' ? this.contentElement.scrollHeight : this.contentElement.scrollWidth, + scrollOffset = this.options.direction == 'vertical' ? this.scrollContentElement.scrollTop : this.scrollContentElement.scrollLeft, + scrollbarSize = this.options.direction == 'vertical' ? this.scrollbarElement.offsetHeight : this.scrollbarElement.offsetWidth, + scrollbarRatio = scrollbarSize / contentSize, + handleOffset = Math.round(scrollbarRatio * scrollOffset) + 2, + handleSize = Math.floor(scrollbarRatio * (scrollbarSize - 2)) - 2; + + if (scrollbarSize < contentSize) { + if (this.options.direction == 'vertical') + this.dragHandleElement.setAttribute('style', 'top: ' + handleOffset + 'px; height: ' + handleSize + 'px') + else + this.dragHandleElement.setAttribute('style', 'left: ' + handleOffset + 'px; width: ' + handleSize + 'px') + + this.scrollbarElement.removeAttribute('data-hidden') + } + else + this.scrollbarElement.setAttribute('data-hidden', true) + } + + Scrollpad.prototype.displayScrollbar = function() { + this.clearUpdateScrollbarTimer() + + this.updateScrollbarSize() + this.scrollbarElement.setAttribute('data-visible', 'true') + } + + Scrollpad.prototype.hideScrollbar = function() { + this.scrollbarElement.removeAttribute('data-visible') + } + + Scrollpad.prototype.clearUpdateScrollbarTimer = function() { + if (this.updateScrollbarTimer === null) + return + + clearTimeout(this.updateScrollbarTimer) + this.updateScrollbarTimer = null + } + + // EVENT HANDLERS + // ============================ + + Scrollpad.prototype.onMouseEnter = function() { + this.displayScrollbar() + } + + Scrollpad.prototype.onMouseLeave = function() { + this.hideScrollbar() + } + + Scrollpad.prototype.onScroll = function() { + if (this.updateScrollbarTimer !== null) + return + + this.updateScrollbarTimer = setTimeout(this.proxy(this.displayScrollbar), 10) + } + + Scrollpad.prototype.onStartDrag = function(ev) { + $.wn.foundation.event.stop(ev) + + var pageCoords = $.wn.foundation.event.pageCoordinates(ev), + eventOffset = this.options.direction == 'vertical' ? pageCoords.y : pageCoords.x, + handleCoords = $.wn.foundation.element.absolutePosition(this.dragHandleElement), + handleOffset = this.options.direction == 'vertical' ? handleCoords.top : handleCoords.left + + this.dragOffset = eventOffset - handleOffset + + document.addEventListener('mousemove', this.proxy(this.onMouseMove)) + document.addEventListener('mouseup', this.proxy(this.onEndDrag)) + } + + Scrollpad.prototype.onMouseMove = function(ev) { + $.wn.foundation.event.stop(ev) + + var eventCoordsAttr = this.options.direction == 'vertical' ? 'y' : 'x', + elementCoordsAttr = this.options.direction == 'vertical' ? 'top' : 'left', + offsetAttr = this.options.direction == 'vertical' ? 'offsetHeight' : 'offsetWidth', + scrollAttr = this.options.direction == 'vertical' ? 'scrollTop' : 'scrollLeft' + + var eventOffset = $.wn.foundation.event.pageCoordinates(ev)[eventCoordsAttr], + scrollbarOffset = $.wn.foundation.element.absolutePosition(this.scrollbarElement)[elementCoordsAttr], + dragPos = eventOffset - scrollbarOffset - this.dragOffset, + scrollbarSize = this.scrollbarElement[offsetAttr], + contentSize = this.contentElement[offsetAttr], + dragPerc = dragPos / scrollbarSize + + if (dragPerc > 1) + dragPerc = 1 + + var scrollPos = dragPerc * contentSize; + + this.scrollContentElement[scrollAttr] = scrollPos + } + + Scrollpad.prototype.onEndDrag = function(ev) { + document.removeEventListener('mousemove', this.proxy(this.onMouseMove)) + document.removeEventListener('mouseup', this.proxy(this.onEndDrag)) + } + + // SCROLLPAD PLUGIN DEFINITION + // ============================ + + Scrollpad.DEFAULTS = { + direction: 'vertical' + } + + var old = $.fn.scrollpad + + $.fn.scrollpad = function (option) { + var args = Array.prototype.slice.call(arguments, 1), + result = undefined + + this.each(function () { + var $this = $(this) + var data = $this.data('oc.scrollpad') + var options = $.extend({}, Scrollpad.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.scrollpad', (data = new Scrollpad(this, options))) + if (typeof option == 'string') result = data[option].apply(data, args) + if (typeof result != 'undefined') return false + }) + + return result ? result : this + } + + $.fn.scrollpad.Constructor = Scrollpad + + // SCROLLPAD NO CONFLICT + // ================= + + $.fn.scrollpad.noConflict = function () { + $.fn.scrollpad = old + return this + } + + // SCROLLPAD DATA-API + // =============== + + $(document).on('render', function(){ + $('div[data-control=scrollpad]').scrollpad() + }) +}(window.jQuery); \ No newline at end of file diff --git a/modules/backend/assets/js/winter.sidenav-tree.js b/modules/backend/assets/js/winter.sidenav-tree.js new file mode 100644 index 0000000..4415486 --- /dev/null +++ b/modules/backend/assets/js/winter.sidenav-tree.js @@ -0,0 +1,268 @@ +/* + * Side navigation tree + * + * Data attributes: + * - data-control="sidenav-tree" - enables the plugin + * - data-tree-name - unique name of the tree control. The name is used for storing user configuration in the browser cookies. + * + * JavaScript API: + * $('#tree').sidenavTree() + * + * Dependences: + * - Null + */ + ++function ($) { "use strict"; + + // SIDENAVTREE CLASS DEFINITION + // ============================ + + var SidenavTree = function(element, options) { + this.options = options + this.$el = $(element) + + this.init() + } + + SidenavTree.DEFAULTS = { + treeName: 'sidenav_tree' + } + + SidenavTree.prototype.init = function (){ + var self = this + + $(document.body).addClass('has-sidenav-tree') + + this.statusCookieName = this.options.treeName + 'groupStatus' + this.searchCookieName = this.options.treeName + 'search' + this.$searchInput = $(this.options.searchInput) + + this.$el.on('click', 'li > div.group', function() { + self.toggleGroup($(this).closest('li')) + return false + }) + + this.$searchInput.on('input', function(){ + self.handleSearchChange() + }) + + var searchTerm = $.cookie(this.searchCookieName) + if (searchTerm !== undefined && searchTerm.length > 0) { + this.$searchInput.val(searchTerm) + this.applySearch() + } + + var scrollbar = $('[data-control=scrollbar]', this.$el).data('oc.scrollbar'), + active = $('li.active', this.$el) + + if (active.length > 0) { + scrollbar.gotoElement(active) + } + } + + SidenavTree.prototype.toggleGroup = function(group) { + var $group = $(group), + status = $group.attr('data-status') + + status === undefined || status == 'expanded' + ? this.collapseGroup($group) + : this.expandGroup($group) + } + + SidenavTree.prototype.collapseGroup = function(group) { + var + $list = $('> ul', group), + self = this + + $list.css('overflow', 'hidden') + $list.animate({ 'height': 0 }, { + duration: 100, + queue: false, + complete: function() { + $list.css({ + 'overflow': 'visible', + 'display': 'none' + }) + + $(group).attr('data-status', 'collapsed') + $(window).trigger('oc.updateUi') + self.saveGroupStatus($(group).data('group-code'), true) + } + }) + } + + SidenavTree.prototype.expandGroup = function(group, duration) { + var + $list = $('> ul', group), + self = this + + duration = duration === undefined ? 100 : duration + + $list.css({ + 'overflow': 'hidden', + 'height': 0 + }) + $list.animate({'height': $list[0].scrollHeight}, { duration: duration, queue: false, complete: function() { + $list.css({ + 'overflow': 'visible', + 'height': 'auto', + 'display': '' + }) + $(group).attr('data-status', 'expanded') + $(window).trigger('oc.updateUi') + self.saveGroupStatus($(group).data('group-code'), false) + } }) + } + + SidenavTree.prototype.saveGroupStatus = function(groupCode, collapsed) { + var collapsedGroups = $.cookie(this.statusCookieName), + updatedGroups = [] + + if (collapsedGroups === undefined) { + collapsedGroups = '' + } + + collapsedGroups = collapsedGroups.split('|') + $.each(collapsedGroups, function() { + if (groupCode != this) + updatedGroups.push(this) + }) + + if (collapsed) { + updatedGroups.push(groupCode) + } + + $.cookie(this.statusCookieName, updatedGroups.join('|'), { expires: 30, path: '/' }) + } + + SidenavTree.prototype.handleSearchChange = function() { + var lastValue = this.$searchInput.data('oc.lastvalue'); + + if (lastValue !== undefined && lastValue == this.$searchInput.val()) { + return + } + + this.$searchInput.data('oc.lastvalue', this.$searchInput.val()) + + if (this.dataTrackInputTimer !== undefined) { + window.clearTimeout(this.dataTrackInputTimer) + } + + var self = this + this.dataTrackInputTimer = window.setTimeout(function(){ + self.applySearch() + }, 300); + + $.cookie(this.searchCookieName, $.trim(this.$searchInput.val()), { expires: 30, path: '/' }) + } + + SidenavTree.prototype.applySearch = function() { + var query = $.trim(this.$searchInput.val()), + words = query.toLowerCase().split(' '), + visibleGroups = [], + visibleItems = [], + self = this + + if (query.length == 0) { + $('li', this.$el).removeClass('hidden') + + return + } + + /* + * Find visible groups and items + */ + $('ul.top-level > li', this.$el).each(function() { + var $li = $(this) + + if (self.textContainsWords($('div.group h3', $li).text(), words)) { + visibleGroups.push($li.get(0)) + + $('ul li', $li).each(function(){ + visibleItems.push(this) + }) + } + else { + $('ul li', $li).each(function(){ + if (self.textContainsWords($(this).text(), words) || self.textContainsWords($(this).data('keywords'), words)) { + visibleGroups.push($li.get(0)) + visibleItems.push(this) + } + }) + } + }) + + /* + * Hide invisible groups and items + */ + $('ul.top-level > li', this.$el).each(function() { + var $li = $(this), + groupIsVisible = $.inArray(this, visibleGroups) !== -1 + + $li.toggleClass('hidden', !groupIsVisible) + if (groupIsVisible) + self.expandGroup($li, 0) + + $('ul li', $li).each(function(){ + var $itemLi = $(this) + + $itemLi.toggleClass('hidden', $.inArray(this, visibleItems) == -1) + }) + }) + + return false + } + + SidenavTree.prototype.textContainsWords = function(text, words) { + text = text.toLowerCase() + + for (var i = 0; i < words.length; i++) { + if (text.indexOf(words[i]) === -1) + return false + } + + return true + } + + // SIDENAVTREE PLUGIN DEFINITION + // ============================ + + var old = $.fn.sidenavTree + + $.fn.sidenavTree = function (option) { + var args = arguments; + + return this.each(function () { + var $this = $(this) + var data = $this.data('oc.sidenavTree') + var options = $.extend({}, SidenavTree.DEFAULTS, $this.data(), typeof option == 'object' && option) + + if (!data) $this.data('oc.sidenavTree', (data = new SidenavTree(this, options))) + if (typeof option == 'string') { + var methodArgs = []; + for (var i=1; i') + + this.$fixButton.click(function() { + self.fixPanel() + return false + }) + $('.fix-button-container', this.$el).append(this.$fixButton) + + this.$sideNavItems.click(function() { + if ($(this).data('no-side-panel')) { + return + } + + if (Modernizr.touchevents && $(window).width() < self.options.breakpoint) { + if ($(this).data('menu-item') == self.visibleItemId && self.panelVisible) { + self.hideSidePanel() + return + } + else { + self.displaySidePanel() + } + } + + self.displayTab(this) + + return false + }) + + if (!Modernizr.touchevents) { + // The side panel now opens only when a menu item is hovered and + // when the item doesn't have the "data-no-side-panel" attribute. + // TODO: remove the comment and the code below if no issues noticed. + // self.$sideNav.mouseenter(function() { + // if ($(window).width() < self.options.breakpoint || !self.panelFixed()) { + // self.panelOpenTimeout = setTimeout(function() { + // self.displaySidePanel() + // }, self.tabOpenDelay) + // } + // }) + + self.$sideNav.mouseleave(function() { + clearTimeout(self.panelOpenTimeout) + }) + + self.$el.mouseleave(function() { + self.hideSidePanel() + }) + + self.$sideNavItems.mouseenter(function() { + if ($(window).width() < self.options.breakpoint || !self.panelFixed()) { + if ($(this).data('no-side-panel')) { + self.hideSidePanel() + return + } + + var _this = this + self.tabOpenTimeout = setTimeout(function() { + self.displaySidePanel() + self.displayTab(_this) + }, self.tabOpenDelay) + } + }) + + self.$sideNavItems.mouseleave(function() { + clearTimeout(self.tabOpenTimeout) + }) + + $(window).resize(function() { + self.updatePanelPosition() + self.updateActiveTab() + }) + } + else { + $('#layout-body').click(function() { + if (self.panelVisible) { + self.hideSidePanel() + return false + } + }) + + self.$el.on('close.oc.sidePanel', function() { + self.hideSidePanel() + }) + } + + this.updateActiveTab() + } + + SidePanelTab.prototype.displayTab = function(menuItem) { + var menuItemId = $(menuItem).data('menu-item') + + this.visibleItemId = menuItemId + + if ($.wn.sideNav !== undefined) { + $.wn.sideNav.setActiveItem(menuItemId) + } + + this.$sidePanelItems.each(function() { + var $el = $(this) + $el.toggleClass('hide', $el.data('content-id') != menuItemId) + }) + + $(window).trigger('resize') + } + + SidePanelTab.prototype.displaySidePanel = function() { + $(document.body).addClass('display-side-panel') + + this.$el.appendTo('#layout-canvas') + this.panelVisible = true + this.$el.css({ + left: this.sideNavWidth, + top: this.mainNavHeight + }) + + this.updatePanelPosition() + $(window).trigger('resize') + } + + SidePanelTab.prototype.hideSidePanel = function() { + $(document.body).removeClass('display-side-panel') + if (this.$el.next('#layout-body').length == 0) { + $('#layout-body').before(this.$el) + } + + this.panelVisible = false + + this.updateActiveTab() + } + + SidePanelTab.prototype.updatePanelPosition = function() { + if (!this.panelFixed() || Modernizr.touchevents) { + this.$el.height($(document).height() - this.mainNavHeight) + } + else { + this.$el.css('height', '') + } + + if (this.panelVisible && $(window).width() > this.options.breakpoint && this.panelFixed()) { + this.hideSidePanel() + } + } + + SidePanelTab.prototype.updateActiveTab = function() { + if ($.wn.sideNav === undefined) { + return + } + + if (!this.panelVisible && ($(window).width() < this.options.breakpoint || !this.panelFixed())) { + $.wn.sideNav.unsetActiveItem() + } + else { + $.wn.sideNav.setActiveItem(this.visibleItemId) + } + } + + SidePanelTab.prototype.panelFixed = function() { + return !($(window).width() < this.options.breakpoint) && + !$(document.body).hasClass('side-panel-not-fixed') + } + + SidePanelTab.prototype.fixPanel = function() { + $(document.body).toggleClass('side-panel-not-fixed') + + var self = this + + window.setTimeout(function() { + var fixed = self.panelFixed() + + if (fixed) { + self.updateActiveTab() + $(document.body).addClass('side-panel-fix-shadow') + } else { + $(document.body).removeClass('side-panel-fix-shadow') + self.hideSidePanel() + } + + if (typeof(localStorage) !== 'undefined') + localStorage.ocSidePanelFixed = fixed ? 1 : 0 + }, 0) + } + + SidePanelTab.DEFAULTS = { + breakpoint: 769 + } + + // PLUGIN DEFINITION + // ============================ + + var old = $.fn.sidePanelTab + + $.fn.sidePanelTab = function (option) { + return this.each(function() { + var $this = $(this) + var data = $this.data('oc.sidePanelTab') + var options = $.extend({}, SidePanelTab.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.sidePanelTab', (data = new SidePanelTab(this, options))) + if (typeof option == 'string') data[option].call(data) + }) + } + + $.fn.sidePanelTab.Constructor = SidePanelTab + + // NO CONFLICT + // ================= + + $.fn.sidePanelTab.noConflict = function() { + $.fn.sidePanelTab = old + return this + } + + // DATA-API + // ============ + + $(document).ready(function(){ + $('[data-control=layout-sidepanel]').sidePanelTab() + }) + + // STORED PREFERENCES + // ==================== + + $(document).ready(function() { + if (Modernizr.touchevents || (typeof(localStorage) !== 'undefined')) { + if (localStorage.ocSidePanelFixed == 0) { + $(document.body).addClass('side-panel-not-fixed') + $(window).trigger('resize') + } + else if (localStorage.ocSidePanelFixed == 1) { + $(document.body).removeClass('side-panel-not-fixed') + $(window).trigger('resize') + } + } + }) +}(window.jQuery); diff --git a/modules/backend/assets/js/winter.simplelist.js b/modules/backend/assets/js/winter.simplelist.js new file mode 100644 index 0000000..f1158c7 --- /dev/null +++ b/modules/backend/assets/js/winter.simplelist.js @@ -0,0 +1,81 @@ +/* + * SimpleList control. + * + * Data attributes: + * - data-control="simplelist" - enables the simplelist plugin + * + * JavaScript API: + * $('#simplelist').simplelist() + * + * Dependences: + * - Sortable (jquery-sortable.js) + */ ++function ($) { "use strict"; + + var SimpleList = function (element, options) { + + var $el = this.$el = $(element) + + this.options = options || {} + + if ($el.hasClass('is-sortable')) { + + /* + * Make each list inside sortable + */ + var sortableOptions = { + distance: 10 + } + if (this.options.sortableHandle) + sortableOptions[handle] = this.options.sortableHandle + + $el.find('> ul, > ol').sortable(sortableOptions) + } + + if ($el.hasClass('is-scrollable')) { + + /* + * Inject a scrollbar container + */ + $el.wrapInner($('
').addClass('control-scrollbar')) + var $scrollbar = $el.find('>.control-scrollbar:first') + $scrollbar.scrollbar() + } + } + + SimpleList.DEFAULTS = { + sortableHandle: null + } + + // SIMPLE LIST PLUGIN DEFINITION + // ============================ + + var old = $.fn.simplelist + + $.fn.simplelist = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('oc.simplelist') + var options = $.extend({}, SimpleList.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.simplelist', (data = new SimpleList(this, options))) + }) + } + + $.fn.simplelist.Constructor = SimpleList + + // SIMPLE LIST NO CONFLICT + // ================= + + $.fn.simplelist.noConflict = function () { + $.fn.simplelist = old + return this + } + + // SIMPLE LIST DATA-API + // =============== + + $(document).render(function(){ + $('[data-control="simplelist"]').simplelist() + }) + +}(window.jQuery); diff --git a/modules/backend/assets/js/winter.tabformexpandcontrols.js b/modules/backend/assets/js/winter.tabformexpandcontrols.js new file mode 100644 index 0000000..f1195f0 --- /dev/null +++ b/modules/backend/assets/js/winter.tabformexpandcontrols.js @@ -0,0 +1,163 @@ +/* + * Extends the fancy tabs layout with expand controls in the tab + * form sections. See main Builder page for example. + * TODO: A similar layout is used in the CMS, Pages and Builder areas, + * but only Builder uses this class. + */ ++function ($) { "use strict"; + var Base = $.wn.foundation.base, + BaseProto = Base.prototype + + var TabFormExpandControls = function ($tabsControlElement, options) { + this.$tabsControlElement = $tabsControlElement + this.options = $.extend(TabFormExpandControls.DEFAULTS, typeof options == 'object' && options) + this.tabsControlId = null + + Base.call(this) + this.init() + } + + TabFormExpandControls.prototype = Object.create(BaseProto) + TabFormExpandControls.prototype.constructor = TabFormExpandControls + + TabFormExpandControls.prototype.init = function() { + this.tabsControlId = this.$tabsControlElement.attr('id') + + if (!this.tabsControlId) { + throw new Error('The tab controls element should have the id attribute value.') + } + + this.registerHandlers() + } + + TabFormExpandControls.prototype.dispose = function() { + this.unregisterHandlers() + + this.$tabsControlElement = null + + BaseProto.dispose.call(this) + } + + TabFormExpandControls.prototype.registerHandlers = function() { + this.$tabsControlElement.on('initTab.oc.tab', this.proxy(this.initTab)) + this.$tabsControlElement.on('click', '[data-control="tabless-collapse-icon"]', this.proxy(this.tablessCollapseClicked)) + this.$tabsControlElement.on('click', '[data-control="primary-collapse-icon"]', this.proxy(this.primaryCollapseClicked)) + } + + TabFormExpandControls.prototype.unregisterHandlers = function() { + this.$tabsControlElement.off('initTab.oc.tab', this.proxy(this.initTab)) + this.$tabsControlElement.off('click', '[data-control="tabless-collapse-icon"]', this.proxy(this.tablessCollapseClicked)) + this.$tabsControlElement.off('click', '[data-control="primary-collapse-icon"]', this.proxy(this.primaryCollapseClicked)) + } + + TabFormExpandControls.prototype.initTab = function(ev, data) { + if ($(ev.target).attr('id') != this.tabsControlId) + return + + var $primaryPanel = this.findPrimaryPanel(data.pane), + $panel = $('.form-tabless-fields', data.pane), + $secondaryPanel = this.findSecondaryPanel(data.pane), + hasSecondaryTabs = $secondaryPanel.length > 0 + + $secondaryPanel.addClass('secondary-content-tabs') + $panel.append(this.createTablessCollapseIcon()) + + if (!hasSecondaryTabs) { + $('.tab-pane', $primaryPanel).addClass('pane-compact') + } + + $('.nav-tabs', $primaryPanel).addClass('master-area') + + if ($primaryPanel.length > 0) { + $secondaryPanel.append(this.createPrimaryCollapseIcon()) + } else { + $secondaryPanel.addClass('primary-collapsed') + } + + if (!$('a', data.tab).hasClass('new-template') && this.getLocalStorageValue('tabless', 0) == 1) { + $panel.addClass('collapsed') + } + + if (this.getLocalStorageValue('primary', 0) == 1 && hasSecondaryTabs) { + $primaryPanel.addClass('collapsed') + $secondaryPanel.addClass('primary-collapsed') + } + + if (this.options.onInitTab) { + this.options.onInitTab($('form', data.pane)) + } + } + + TabFormExpandControls.prototype.tablessCollapseClicked = function(ev) { + var $panel = $(ev.target).closest('.form-tabless-fields') + + $panel.toggleClass('collapsed') + this.setLocalStorageValue('tabless', $panel.hasClass('collapsed') ? 1 : 0) + window.setTimeout(this.proxy(this.updateUi), 500) + + ev.stopPropagation() + return false + } + + TabFormExpandControls.prototype.primaryCollapseClicked = function(ev) { + var $pane = $(ev.target).closest('.tab-pane'), + $primaryPanel = this.findPrimaryPanel($pane), + $secondaryPanel = this.findSecondaryPanel($pane) + + $primaryPanel.toggleClass('collapsed') + $secondaryPanel.toggleClass('primary-collapsed') + + this.updateUi() + this.setLocalStorageValue('primary', $primaryPanel.hasClass('collapsed') ? 1 : 0) + + return false + } + + TabFormExpandControls.prototype.updateUi = function() { + $(window).trigger('oc.updateUi') + } + + TabFormExpandControls.prototype.createTablessCollapseIcon = function() { + return $('') + } + + TabFormExpandControls.prototype.createPrimaryCollapseIcon = function() { + return $('') + } + + TabFormExpandControls.prototype.generateStorageKey = function(section) { + return 'oc' + section + this.tabsControlId.replace('-', '') + 'collapsed' + } + + TabFormExpandControls.prototype.findPrimaryPanel = function(pane) { + return $(pane).find('.control-tabs.primary-tabs') + } + + TabFormExpandControls.prototype.findSecondaryPanel = function(pane) { + return $(pane).find('.control-tabs.secondary-tabs') + } + + TabFormExpandControls.prototype.getLocalStorageValue = function(section, defaultValue) { + var key = this.generateStorageKey(section) + + if (typeof(localStorage) !== 'undefined') { + return localStorage[key] + } + + return defaultValue + } + + TabFormExpandControls.prototype.setLocalStorageValue = function(section, value) { + var key = this.generateStorageKey(section) + + if (typeof(localStorage) !== 'undefined') { + localStorage[key] = value + } + } + + TabFormExpandControls.DEFAULTS = { + onInitTab: null + } + + $.wn.tabFormExpandControls = TabFormExpandControls +}(window.jQuery); \ No newline at end of file diff --git a/modules/backend/assets/js/winter.treelist.js b/modules/backend/assets/js/winter.treelist.js new file mode 100644 index 0000000..10290ac --- /dev/null +++ b/modules/backend/assets/js/winter.treelist.js @@ -0,0 +1,133 @@ +/* + * TreeList Widget + * + * Supported options: + * - handle - class name to use as a handle + * - nested - set to false if sorting should be kept within each OL container, if using + * a handle it should be focused enough to exclude nested handles. + * + * Events: + * - move.oc.treelist - triggered when a node on the tree is moved. + * + * Dependences: + * - Sortable Plugin (winter.sortable.js) + */ ++function ($) { "use strict"; + var Base = $.wn.foundation.base, + BaseProto = Base.prototype + + var TreeListWidget = function (element, options) { + this.$el = $(element) + this.options = options || {}; + + Base.call(this) + + $.wn.foundation.controlUtils.markDisposable(element) + this.init() + } + + TreeListWidget.prototype = Object.create(BaseProto) + TreeListWidget.prototype.constructor = TreeListWidget + + TreeListWidget.prototype.init = function() { + var sortableOptions = { + handle: this.options.handle, + nested: this.options.nested, + onDrop: this.proxy(this.onDrop), + afterMove: this.proxy(this.onAfterMove) + } + + this.$el.find('> ol').sortable($.extend(sortableOptions, this.options)) + + if (!this.options.nested) + this.$el.find('> ol ol').sortable($.extend(sortableOptions, this.options)) + + this.$el.one('dispose-control', this.proxy(this.dispose)) + } + + TreeListWidget.prototype.dispose = function() { + this.unbind() + BaseProto.dispose.call(this) + } + + TreeListWidget.prototype.unbind = function() { + this.$el.off('dispose-control', this.proxy(this.dispose)) + + this.$el.find('> ol').sortable('destroy') + + if (!this.options.nested) { + this.$el.find('> ol ol').sortable('destroy') + } + + this.$el.removeData('oc.treelist') + + this.$el = null + this.options = null + } + + TreeListWidget.DEFAULTS = { + handle: null, + nested: true + } + + // TREELIST EVENT HANDLERS + // ============================ + + TreeListWidget.prototype.onDrop = function($item, container, _super) { + // The event handler could be registered after the + // sortable is destroyed. This should be fixed later. + if (!this.$el) { + return + } + + this.$el.trigger('move.oc.treelist', { item: $item, container: container }) + _super($item, container) + } + + TreeListWidget.prototype.onAfterMove = function($placeholder, container, $closestEl) { + if (!this.$el) { + return + } + + this.$el.trigger('aftermove.oc.treelist', { placeholder: $placeholder, container: container, closestEl: $closestEl }) + } + + // TREELIST WIDGET PLUGIN DEFINITION + // ============================ + + var old = $.fn.treeListWidget + + $.fn.treeListWidget = function (option) { + var args = arguments, + result + + this.each(function () { + var $this = $(this) + var data = $this.data('oc.treelist') + var options = $.extend({}, TreeListWidget.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.treelist', (data = new TreeListWidget(this, options))) + if (typeof option == 'string') result = data[option].call(data) + if (typeof result != 'undefined') return false + }) + + return result ? result : this + } + + $.fn.treeListWidget.Constructor = TreeListWidget + + // TREELIST WIDGET NO CONFLICT + // ================= + + $.fn.treeListWidget.noConflict = function () { + $.fn.treeListWidget = old + return this + } + + // TREELIST WIDGET DATA-API + // ============== + + $(document).render(function(){ + $('[data-control="treelist"]').treeListWidget(); + }) + +}(window.jQuery); \ No newline at end of file diff --git a/modules/backend/assets/js/winter.treeview.js b/modules/backend/assets/js/winter.treeview.js new file mode 100644 index 0000000..f2cef65 --- /dev/null +++ b/modules/backend/assets/js/winter.treeview.js @@ -0,0 +1,437 @@ +/* + * TreeView Widget. Represents a sortable and draggable tree view. This widget was first used in the Pages plugin, for the sidebar page tree. + * + * Data attributes: + * - data-group-status-handler - AJAX handler to execute when an item is collapsed or expanded by a user + * - data-reorder-handler - AJAX handler to execute when items are reordered + * + * Events + * - open.oc.treeview - this event is triggered on the list element when an item is clicked. + * + * Dependences: + * - Tree list (winter.treelist.js) + * + */ ++function ($) { "use strict"; + var Base = $.wn.foundation.base, + BaseProto = Base.prototype + + var TreeView = function (element, options) { + this.$el = $(element) + this.options = options + this.$allItems = null + this.$scrollbar = null + + Base.call(this) + + $.wn.foundation.controlUtils.markDisposable(element) + this.init() + } + + TreeView.prototype = Object.create(BaseProto) + TreeView.prototype.constructor = TreeView + + TreeView.prototype.init = function () { + this.$allItems = $('li', this.$el) + this.$scrollbar = this.$el.closest('[data-control=scrollbar]') + + /* + * Init the sortable + */ + + this.initSortable() + + /* + * Create expand/collapse icons and drag handles + */ + + this.createItemControls() + + /* + * Bind the click events + */ + + this.$el.on('click.treeview', 'li > div > ul.submenu li a', this.proxy(this.onOpenSubmenu)) + this.$el.on('click.treeview', 'li > div > a', this.proxy(this.onOpen)) + this.$el.on('click.treeview', 'li span.expand', this.proxy(this.onItemExpandClick)) + + /* + * Listen for the AJAX updates and dispose the widget + */ + + this.$el.one('dispose-control', this.proxy(this.dispose)) + + /* + * Mark previously active item, if it was set + */ + var dataId = this.$el.data('oc.active-item') + if (dataId !== undefined) { + this.markActive(dataId) + } + + this.$scrollbar.on('oc.scrollEnd', this.proxy(this.onScroll)) + } + + TreeView.prototype.dispose = function() { + this.unregisterHandlers() + this.clearScrollTimeout() + + this.options = null + this.$el.removeData('oc.treeView') + this.$el = null + this.$allItems = null + this.$scrollbar = null + + BaseProto.dispose.call(this) + } + + TreeView.prototype.unregisterHandlers = function() { + this.$scrollbar.off('oc.scrollEnd', this.proxy(this.onScroll)) + this.$el.off('.treeview') + this.$el.off('move.oc.treelist', this.proxy(this.onNodeMove)) + this.$el.off('aftermove.oc.treelist', this.proxy(this.onAfterNodeMove)) + this.$el.off('dispose-control', this.proxy(this.dispose)) + } + + TreeView.prototype.createItemControls = function() { + $('li', this.$el).each(function() { + var $container = $('> div', this), + $expand = $('> span.expand', $container) + + if ($expand.length > 0) + return + + $expand = $('Expand') + + $container.prepend($expand) + + if (!$('.drag-handle', $container).length) + $container.append($('Drag')) + + $container.append($('')) + + if ($(this).attr('data-no-drag-mode') !== undefined) + $('span.drag-handle', this).attr('title', 'Dragging is disabled when the Search is active') + }) + } + + TreeView.prototype.collapseGroup = function($group) { + var $subitems = $('> ol', $group) + + $subitems.css({ + 'overflow': 'hidden' + }) + + $subitems.animate({'height': 0}, { duration: 100, queue: false, complete: function() { + $subitems.css({ + 'overflow': 'visible', + 'display': 'none', + 'height' : 'auto' + }) + $group.attr('data-status', 'collapsed') + $(window).trigger('resize') + } }) + + this.sendGroupStatusRequest($group, 0) + } + + TreeView.prototype.expandGroup = function($group) { + var $subitems = $('> ol', $group) + + $subitems.css({ + 'overflow': 'hidden', + 'display': 'block', + 'height': 0 + }) + + $group.attr('data-status', 'expanded') + $subitems.animate({'height': $subitems[0].scrollHeight}, { duration: 100, queue: false, complete: function() { + $subitems.css({ + 'overflow': 'visible', + 'height': 'auto' + }) + $(window).trigger('resize') + } }) + + this.sendGroupStatusRequest($group, 1); + } + + TreeView.prototype.fixSubItems = function() { + $('li', this.$el).each(function(){ + var $li = $(this), + $subitems = $('> ol > li', $li) + $li.toggleClass('has-subitems', $subitems.length > 0) + }) + } + + TreeView.prototype.toggleGroup = function(group) { + var $group = $(group); + + $group.attr('data-status') == 'expanded' + ? this.collapseGroup($group) + : this.expandGroup($group) + } + + TreeView.prototype.sendGroupStatusRequest = function($group, status) { + if (this.options.groupStatusHandler !== undefined) { + var groupId = $group.data('group-id') + + $group.request(this.options.groupStatusHandler, {data: {group: groupId, status: status}}) + } + } + + TreeView.prototype.sendReorderRequest = function() { + if (this.options.reorderHandler === undefined) + return + + var groups = {} + + function iterator($container, node) { + $('> li', $container).each(function(){ + var subnodes = {} + iterator($('> ol', this), subnodes) + + node[$(this).data('groupId')] = subnodes + }) + } + + iterator($('> ol', this.$el), groups) + + this.$el.request(this.options.reorderHandler, {data: {structure: JSON.stringify(groups)}}) + } + + TreeView.prototype.initSortable = function() { + var $noDragItems = $('[data-no-drag-mode]', this.$el) + + if ($noDragItems.length > 0) + return + + if (this.$el.data('oc.treelist')) + this.$el.treeListWidget('unbind') + + this.$el.treeListWidget({ + tweakCursorAdjustment: this.proxy(this.tweakCursorAdjustment), + isValidTarget: this.proxy(this.isValidTarget), + useAnimation: false, + usePlaceholderClone: true, + handle: 'span.drag-handle', + onDrag: this.proxy(this.onDrag), + tolerance: -20 // Give 20px of carry between containers + }) + + this.$el.on('move.oc.treelist', this.proxy(this.onNodeMove)) + this.$el.on('aftermove.oc.treelist', this.proxy(this.onAfterNodeMove)) + } + + TreeView.prototype.markActive = function(dataId) { + $('li', this.$el).removeClass('active') + + if (dataId) + $('li[data-id="'+dataId+'"]', this.$el).addClass('active') + + this.$el.data('oc.active-item', dataId) + } + + // It seems the method is not used anymore as we re-create the control + // instead of updating it. Remove later if nothing weird is noticed. + // -ab Apr 26 2015 + // + TreeView.prototype.update = function() { + this.$allItems = $('li', this.$el) + this.createItemControls() + //this.initSortable() + + var dataId = this.$el.data('oc.active-item') + if (dataId !== undefined) { + this.markActive(dataId) + } + } + + TreeView.prototype.handleMovedNode = function() { + this.$el.trigger('change') + this.$allItems.removeClass('drop-target') + this.fixSubItems() + this.sendReorderRequest() + } + + TreeView.prototype.tweakCursorAdjustment = function(adjustment) { + if (!adjustment) { + return adjustment + } + + if (this.$scrollbar.length > 0) { + adjustment.top -= this.$scrollbar.scrollTop() + } + + return adjustment + } + + TreeView.prototype.isValidTarget = function($item, container) { + return $(container.el).closest('li').attr('data-status') != 'collapsed' + } + + TreeView.DEFAULTS = { + + } + + // TREEVIEW EVENT HANDLERS + // ============================ + + TreeView.prototype.onOpenSubmenu = function(ev) { + var e = $.Event('submenu.oc.treeview', {relatedTarget: ev.currentTarget, clickEvent: ev}) + this.$el.trigger(e, this) + + return false + } + + TreeView.prototype.onOpen = function(ev) { + var e = $.Event('open.oc.treeview', {relatedTarget: $(ev.currentTarget).closest('li').get(0), clickEvent: ev}) + this.$el.trigger(e, ev.currentTarget) + + return false + } + + TreeView.prototype.onNodeMove = function() { + setTimeout(this.proxy(this.handleMovedNode), 50) + } + + TreeView.prototype.onAfterNodeMove = function(ev, data) { + this.$allItems.removeClass('drop-target') + data.container.el.closest('li').addClass('drop-target') + } + + TreeView.prototype.onItemExpandClick = function(ev) { + this.toggleGroup($(ev.currentTarget).closest('li')) + return false + } + + // TREEVIEW SCROLL ON DRAG + // ============================ + + TreeView.prototype.onScroll = function () { + if (!$('body').hasClass('dragging')) { + return + } + + var changed = this.lastScrollPos - this.$scrollbar.scrollTop() + + this.$el.children('ol').each(function() { + var sortable = $(this).data('oc.sortable') + sortable.refresh() + sortable.cursorAdjustment.top += changed // Keep cursor adjustment in sync with scroll + }); + + this.dragCallback() + + this.lastScrollPos = this.$scrollbar.scrollTop() + } + + TreeView.prototype.onDrag = function ($item, position, _super, event) { + this.lastScrollPos = this.$scrollbar.scrollTop() + + this.dragCallback = function() { + _super($item, position, null, event) + }; + + this.clearScrollTimeout() + this.dragCallback() + + if (!this.$scrollbar || this.$scrollbar.length === 0) + return + + if (position.top < 0) { + this.scrollOffset = -10 + Math.floor(position.top / 5) + } + else if (position.top > this.$scrollbar.height()) { + this.scrollOffset = 10 + Math.ceil((position.top - this.$scrollbar.height()) / 5) + } + else { + return + } + + this.dragScroll() + } + + TreeView.prototype.scrollMax = function() { + return this.$el.height() - this.$scrollbar.height() + } + + TreeView.prototype.dragScroll = function() { + var startScrollTop = this.$scrollbar.scrollTop() + var changed + + this.scrollTimeout = null + + this.$scrollbar.scrollTop(Math.min(startScrollTop + this.scrollOffset, this.scrollMax())) + + changed = this.$scrollbar.scrollTop() - startScrollTop + if (changed === 0) { + return + } + + this.$el.children('ol').each(function() { + var sortable = $(this).data('oc.sortable') + sortable.refresh() + sortable.cursorAdjustment.top -= changed // Keep cursor adjustment in sync with scroll + }); + + this.dragCallback() + + this.$scrollbar.data('oc.scrollbar').setThumbPosition() // Update scrollbar position + + this.scrollTimeout = window.setTimeout(this.proxy(this.dragScroll), 100) + } + + TreeView.prototype.clearScrollTimeout = function() { + if (this.scrollTimeout) { + window.clearTimeout(this.scrollTimeout) + this.scrollTimeout = null + } + } + + // TREEVIEW PLUGIN DEFINITION + // ============================ + + var old = $.fn.treeView + + $.fn.treeView = function (option) { + var args = arguments + + return this.each(function () { + var $this = $(this) + var data = $this.data('oc.treeView') + var options = $.extend({}, TreeView.DEFAULTS, $this.data(), typeof option == 'object' && option) + if (!data) $this.data('oc.treeView', (data = new TreeView(this, options))) + + if (typeof option == 'string' && data) { + var methodArgs = []; + for (var i=1; i
').appendTo('body').addClass(this.options.collapsedMenuClass).css('width', 0) + this.menuContainer = $('
').appendTo(this.menuPanel).css('display', 'none') + this.menuElement = this.$el.clone().appendTo(this.menuContainer).css('width', 'auto') + + var self = this + + /* + * Handle the menu toggle click + */ + this.toggle.click(function() { + if (!self.body.hasClass(self.options.bodyMenuOpenClass)) { + var wrapperWidth = self.wrapper.outerWidth() + + self.menuElement.dragScroll('goToStart') + + self.wrapper.css({ + 'position': 'absolute', + 'min-width': self.wrapper.width(), + 'height': '100%' + }) + self.body.addClass(self.options.bodyMenuOpenClass) + self.menuContainer.css('display', 'block') + + self.wrapper.animate({'left': self.options.menuWidth}, { duration: 200, queue: false }) + self.menuPanel.animate({'width': self.options.menuWidth}, { + duration: 200, + queue: false, + complete: function() { + self.menuElement.css('width', self.options.menuWidth) + } + }) + } + else { + closeMenu() + } + + return false + }) + + this.wrapper.click(function() { + if (self.body.hasClass(self.options.bodyMenuOpenClass)) { + closeMenu() + return false + } + }) + + /* + * Disable the menu if the window is wider than the breakpoint width + */ + $(window).resize(function() { + if (self.body.hasClass(self.options.bodyMenuOpenClass)) { + if ($(window).width() > self.breakpoint) { + hideMenu() + } + } + }) + + /* + * Make the menu draggable + */ + this.menuElement.dragScroll({ + vertical: true, + useNative: true, + start: function(){self.menuElement.addClass('drag')}, + stop: function(){self.menuElement.removeClass('drag')}, + scrollClassContainer: self.menuPanel, + scrollMarkerContainer: self.menuContainer + }) + + this.menuElement.on('click', function() { + // Do not handle menu item clicks while dragging + if (self.menuElement.hasClass('drag')) + return false + }) + + /* + * Internal event, completely hides the menu + */ + function hideMenu() { + self.body.removeClass(self.options.bodyMenuOpenClass) + self.wrapper.css({ + 'position': 'static', + 'min-width': 0, + 'right': 0, + 'height': '100%' + }) + self.menuPanel.css('width', 0) + self.menuElement.css('width', 'auto') + self.menuContainer.css('display', 'none') + } + + /* + * Internal event, smoothly collapses the menu + */ + function closeMenu() { + self.wrapper.animate({'left': 0}, { duration: 200, queue: false}) + self.menuPanel.animate({'width': 0}, { duration: 200, queue: false, complete: hideMenu }) + self.menuElement.animate({'width': 0}, { duration: 200, queue: false }) + } + } + + VerticalMenu.DEFAULTS = { + menuWidth: 230, + breakpoint: 769, + bodyMenuOpenClass: 'mainmenu-open', + collapsedMenuClass: 'mainmenu-collapsed', + contentWrapper: '#layout-canvas' + } + + // VERTICAL MENU PLUGIN DEFINITION + // ============================ + + var old = $.fn.verticalMenu + + $.fn.verticalMenu = function (toggleSelector, option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('oc.verticalMenu') + var options = typeof option == 'object' && option + + if (!data) $this.data('oc.verticalMenu', (data = new VerticalMenu(this, toggleSelector, options))) + if (typeof option == 'string') data[option].call($this) + }) + } + + $.fn.verticalMenu.Constructor = VerticalMenu + + // VERTICAL MENU NO CONFLICT + // ================= + + $.fn.verticalMenu.noConflict = function () { + $.fn.verticalMenu = old + return this + } + +}(window.jQuery); diff --git a/modules/backend/assets/less/.gitignore b/modules/backend/assets/less/.gitignore new file mode 100644 index 0000000..2318862 --- /dev/null +++ b/modules/backend/assets/less/.gitignore @@ -0,0 +1 @@ +*.css \ No newline at end of file diff --git a/modules/backend/assets/less/controls/alert.less b/modules/backend/assets/less/controls/alert.less new file mode 100644 index 0000000..6143c46 --- /dev/null +++ b/modules/backend/assets/less/controls/alert.less @@ -0,0 +1,37 @@ +// +// Custom alerts (Based on Sweet Alert) +// -------------------------------------------------- + +.sweet-overlay { + background-color: @overlay-background; + z-index: @zindex-alert - 1; +} + +.sweet-alert { + text-align: right; + border-radius: @border-radius-base; + .box-shadow(@popup-box-shadow); + z-index: @zindex-alert; + + h2 { + word-break: break-word; + word-wrap: break-word; + max-height: 350px; + overflow-y: auto; + + margin: 10px 0 17px 0; + color: #2b3e50; + text-align: left; + font-size: 15px; + line-height: 23px; + } + + p { + margin: 0; + } + + p.text-muted { + margin-bottom: 20px; + color: #555555; + } +} diff --git a/modules/backend/assets/less/controls/common.less b/modules/backend/assets/less/controls/common.less new file mode 100644 index 0000000..2c8ac65 --- /dev/null +++ b/modules/backend/assets/less/controls/common.less @@ -0,0 +1,66 @@ +// +// Common control styles +// -------------------------------------------------- + +// +// The scroll panel can host a scrollbar control. It has a right border that covers +// the scrollbar to satisfy the design requirements. +// +.control-scrollpanel { + position: relative; + background: @color-panel-light; + + .control-scrollbar { + &.vertical > .scrollbar-scrollbar {right: 0;} + } +} + +.tooltip { + .tooltip-inner { + text-align: left; + padding: 5px 8px; + } + + &.in { + .opacity(1); + } +} + +// +// Logos +// + +.wn-logo-white, .oc-logo-white { + background-image: url(../images/winter-logo-white.svg); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: contain; +} + +.wn-logo, .oc-logo { + background-image: url(../images/winter-logo.svg); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: contain; +} + +.layout.control-tabs.wn-logo-transparent:not(.has-tabs), .layout.control-tabs.oc-logo-transparent:not(.has-tabs), +.flex-layout-column.wn-logo-transparent:not(.has-tabs), .flex-layout-column.oc-logo-transparent:not(.has-tabs), +.layout-cell.wn-logo-transparent, .layout-cell.oc-logo-transparent { + background-size: 50% auto; + background-repeat: no-repeat; + background-image: url(../images/winter-logo.svg); + background-position: 50% 50%; + position: relative; + + &:after { + content: ''; + display: table-cell; + position: absolute; + left: 0; + top: 0; + height: 100%; + width: 100%; + background: rgba(249,249,249,0.7); + } +} diff --git a/modules/backend/assets/less/controls/filelist.less b/modules/backend/assets/less/controls/filelist.less new file mode 100644 index 0000000..37ba76c --- /dev/null +++ b/modules/backend/assets/less/controls/filelist.less @@ -0,0 +1,427 @@ +// +// File list control +// -------------------------------------------------- + +.control-filelist { + .listPaddings (@level, @offset-base) when (@level > 0) { + > li.group { + > ul { + > li > a { + padding-left: (@level+2)*@offset-base; + margin-left: -1*@level*@offset-base; + } + + .listPaddings(@level - 1, @offset-base); + } + } + } + .listPaddings (0, 27px) {} + + p.no-data { + padding: 22px 0; + margin: 0; + color: @color-filelist-norecords-text; + font-size: @font-size-base; + text-align: center; + font-weight: normal; + .border-radius(@border-radius-base); + } + + ul { + padding: 0; + margin: 0; + + li { + font-weight: normal; + line-height: 150%; + position: relative; + list-style: none; + + a:hover { + background: @color-list-hover; + } + + &.active > a { + background: @color-list-active; + position: relative; + &:after { + position: absolute; + height: 100%; + width: 4px; + left: 0; + top: 0; + background: @color-list-active-border; + display: block; + content: ' '; + } + } + + a { + display: block; + padding: 10px 45px 10px 20px; + outline: none; + + &:hover, &:focus, &:active {text-decoration: none;} + + span { + display: block; + + &.title { + font-weight: normal; + color: @color-text-title; + font-size: @font-size-base; + } + + &.description { + color: @color-text-description; + font-size: @font-size-base - 2; + white-space: nowrap; + font-weight: normal; + overflow: hidden; + text-overflow: ellipsis; + + strong { + color: @color-text-title; + font-weight: normal; + } + } + } + } + + &.group { + > h4, > div.group > h4 { + font-weight: normal; + font-size: @font-size-base; + margin-top: 0; + margin-bottom: 0; + position: relative; + + a { + padding: 10px 20px 10px 53px; + color: @color-text-title; + position: relative; + outline: none; + + &:hover { background: transparent; } + + &:before, &:after { + width: 10px; + height: 10px; + display: block; + position: absolute; + top: 1px; + } + + &:after { + left: 33px; + top: 9px; + .icon(@folder); + color: @color-list-icon; + font-size: 16px; + } + + &:before { + left: 20px; + top: 9px; + color: @color-list-arrow; + .icon(@caret-right); + .transform( ~'rotate(90deg) translate(5px, 0)' ); + .transition(all 0.1s ease); + } + } + } + + > ul { + > li > a { + padding-left: 52px; + } + + > li.group { + padding-left: 20px; + } + + .listPaddings(10, 27px); + } + + &[data-status=collapsed] { + > h4 a:before, > div.group > h4 a:before { + .transform(~'rotate(0deg) translate(3px, 0)'); + } + + & > ul, & > div.subitems { + display: none; + } + } + } + + > div.controls { + position: absolute; + right: 19px; + top: 6px; + + .dropdown { + width: 14px; + height: 21px; + + &.open a.control { + display: block!important; + &:before { + visibility: visible; + display: block; + } + } + } + + a.control { + color: @color-text-title; + font-size: @font-size-base; + visibility: hidden; + overflow: hidden; + width: 14px; + height: 21px; + display: none; + text-decoration: none; + cursor: pointer; + padding: 0; + .opacity(0.5); + &:before { + visibility: visible; + display: block; + margin-right: 0; + } + + &:hover { + .opacity(1); + } + } + } + + &:hover { + > div.controls, > a.control { + display: block!important; + + > a.control { + display: block!important; + } + } + } + + .checkbox { + position: absolute; + top: -5px; + right: 0; + + label { + margin-right: 0; + + &:before { + border-color: @color-filelist-cb-border; + } + } + } + } + } + + &.single-line { + ul { + li a span.title { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + } + } + + // + // Templates have emphasis + // + + &.filelist-hero { + .a-hover() { + background: @color-filelist-hero-hover-bg; + border-bottom: 1px solid @color-filelist-hero-hover-bg !important; + span.title, span.description { + color: @color-filelist-hero-hover-text !important; + } + + .list-icon { + color: @color-filelist-hero-hover-text !important; + } + } + + .a-active() { + background: @color-filelist-hero-active-bg; + border-bottom: 1px solid @color-filelist-hero-active-bg !important; + span.title, span.description { + color: @color-filelist-hero-active-text !important; + } + + .list-icon { + color: @color-filelist-hero-active-text !important; + } + } + + ul { + li { + background: @color-filelist-hero-item-bg; + border-bottom: none; + + > a { + padding: 11px 45px 10px 50px; + font-size: @font-size-base - 1; + border-bottom: 1px solid @color-panel-light; + + span.title { + font-size: @font-size-base; + font-weight: normal; + color: @color-filelist-title-hero; + } + + span.description { + font-size: @font-size-base - 1; + } + + .list-icon { + position: absolute; + left: 14px; + top: 50%; + transform: translateY(-50%); + font-size: 22px; + color: #b7c0c2; + } + + &:hover { + .a-hover(); + } + + &:active { + .a-active(); + } + } + + .checkbox { + top: -2px; + right: 0; + } + + &.active { + > a { + border-bottom: 1px solid @color-list-active; + + &:after { + top: -1px; + bottom: -1px; + height: auto; + } + + > span.borders { + &:before { + content: ' '; + position: absolute; + width: 100%; + height: 1px; + display: block; + left: 0; + background-color: @color-list-active; + } + + &:before {top: -1px;} + } + + &:hover > span.borders:before { + background-color: @color-filelist-hero-hover-bg; + } + + &:active > span.borders:before { + background-color: @color-filelist-hero-active-bg; + } + } + } + + > h4 { + padding-top: 7px; + padding-bottom: 6px; + border-bottom: 1px solid @color-panel-light; + } + + > div.controls { + display: none; + position: absolute; + right: 16px; + top: 15px; + + > a.control { + width: 16px; + height: 23px; + background: transparent; + overflow: hidden; + display: inline-block; + color: @color-filelist-hero-hover-text!important; + padding: 0; + + &:before { + font-size: 17px; + } + } + } + + &:hover > div.controls { + display: block; + } + + &.separator { + position: relative; + border-bottom: 1px solid #95a5a6; + padding: 12px 15px 13px 15px; + + &:before { + z-index: 31; + .triangle(down, 19px, 11px, white); + position: absolute; + left: 13px; + bottom: -8px; + } + + &:after { + z-index: 30; + .triangle(down, 17px, 9px, #95a5a6); + position: absolute; + left: 14px; + bottom: -9px; + } + + h5 { + color: #2b3e50; + font-size: @font-size-base; + margin: 0; + font-weight: normal; + padding: 0; + } + } + } + + > li.group { + > ul > li > a { + padding-left: 66px; + } + } + } + + &.single-level { + ul li:hover { + background: @color-filelist-hero-hover-bg; + + > a { + .a-hover(); + } + } + ul li:active { + background: @color-filelist-hero-active-bg; + + > a { + .a-active(); + } + } + } + } +} diff --git a/modules/backend/assets/less/controls/global-notice.less b/modules/backend/assets/less/controls/global-notice.less new file mode 100644 index 0000000..8264e6a --- /dev/null +++ b/modules/backend/assets/less/controls/global-notice.less @@ -0,0 +1,25 @@ +.global-notice { + position: sticky; + top: 0; + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 0.5em; + justify-content: space-between; + z-index: 10500; + background: #ab2a1c; + color: #FFF; + padding: 0.5em 0.75em; + + .notice-icon { + font-size: 1.5em; + vertical-align: bottom; + display: inline-block; + margin-right: .25em; + } + + .notice-text { + display: inline-block; + vertical-align:middle; + } +} diff --git a/modules/backend/assets/less/controls/namevaluelist.less b/modules/backend/assets/less/controls/namevaluelist.less new file mode 100644 index 0000000..afd6c1e --- /dev/null +++ b/modules/backend/assets/less/controls/namevaluelist.less @@ -0,0 +1,27 @@ +table.name-value-list { + border-collapse: collapse; + font-size: 13px; + + th, td { + padding: 4px 0 4px 0; + vertical-align: top; + } + + tr:first-child { + th, td { + padding-top: 0; + } + } + + th { + font-weight: 600; + color: #95a5a6; + padding-right: 15px; + text-transform: uppercase; + } + + td { + color: #2b3e50; + word-wrap: break-word; + } +} \ No newline at end of file diff --git a/modules/backend/assets/less/controls/panels.less b/modules/backend/assets/less/controls/panels.less new file mode 100644 index 0000000..02c2312 --- /dev/null +++ b/modules/backend/assets/less/controls/panels.less @@ -0,0 +1,77 @@ +div.panel { + @panel-border-color: #e8eaeb; + + padding: 20px; + + &.no-padding { + padding: 0; + } + + &.no-padding-bottom { + padding-bottom: 0; + } + + &.padding-top { + padding-top: 20px; + } + + &.padding-less { + padding: 15px; + } + + &.transparent { + background: transparent; + } + + &.border-left { + border-left: 1px solid @panel-border-color; + } + + &.border-right { + border-right: 1px solid @panel-border-color; + } + + &.border-bottom { + border-bottom: 1px solid @panel-border-color; + } + + &.border-top { + border-top: 1px solid @panel-border-color; + } + + &.triangle-down { + position: relative; + + &:after { + .triangle(down, 15px, 8px, white); + position: absolute; + left: 15px; + bottom: -8px; + z-index: 101; + } + + &:before { + .triangle(down, 17px, 9px, #e8eaeb); + position: absolute; + left: 14px; + bottom: -9px; + z-index: 100; + } + } + + /* + * Panel sections + */ + + h3.section, > label { + text-transform: uppercase; + color: #95a5a6; + font-size: 13px; + font-weight: 600; + margin: 0 0 15px 0; + } + + > label { + margin-bottom: 5px; + } +} diff --git a/modules/backend/assets/less/controls/record-navigation.less b/modules/backend/assets/less/controls/record-navigation.less new file mode 100644 index 0000000..a9501da --- /dev/null +++ b/modules/backend/assets/less/controls/record-navigation.less @@ -0,0 +1,69 @@ +// +// Record navigation +// +// Previous/next navigation shown in the breadcrumb row of a form, letting the +// user step through the sibling records of the controller's list (respecting +// its active filters, search and sorting). Rendered by the FormController +// behavior via formcontroller/partials/_record_navigation.php. +// ======================================================================== + +.control-breadcrumb { + position: relative; +} + +.form-record-nav { + position: absolute; + top: 0; + bottom: 0; + right: 20px; + display: flex; + align-items: center; + gap: 9px; + font-size: 12px; + + .form-record-nav-position { + color: #5a6b7b; + font-weight: 600; + letter-spacing: .3px; + white-space: nowrap; + } + + .form-record-nav-group { + display: inline-flex; + align-items: center; + background: rgba(255, 255, 255, .55); + border: 1px solid rgba(0, 0, 0, .09); + border-radius: 6px; + overflow: hidden; + box-shadow: 0 1px 1px rgba(0, 0, 0, .03); + } + + .form-record-nav-btn { + display: flex; + align-items: center; + justify-content: center; + width: 28px; + height: 24px; + color: #5a6b7b; + text-decoration: none; + transition: background-color .12s ease, color .12s ease; + + & + .form-record-nav-btn { + border-left: 1px solid rgba(0, 0, 0, .09); + } + + &:not(.is-disabled):hover { + background-color: #fff; + color: #1f2d3d; + } + + &.is-disabled { + color: #b6bfc7; + cursor: default; + } + + svg { + display: block; + } + } +} diff --git a/modules/backend/assets/less/controls/reportwidgets.less b/modules/backend/assets/less/controls/reportwidgets.less new file mode 100644 index 0000000..983762b --- /dev/null +++ b/modules/backend/assets/less/controls/reportwidgets.less @@ -0,0 +1,51 @@ +.report-widget { + padding: 15px; + background: white; + .box-sizing(border-box); + .border-radius(@border-radius-base); + font-size: @font-size-base - 1; + + h3 { + font-size: @font-size-base; + color: @color-report-widget-title; + text-transform: uppercase; + font-weight: 600; + margin-top: 0; + margin-bottom: 30px; + } + + .height-100 { height: 100px; } + .height-200 { height: 200px; } + .height-300 { height: 300px; } + .height-400 { height: 400px; } + .height-500 { height: 500px; } + + p.report-description { + margin-bottom: 0; + margin-top: 15px; + font-size: 12px; + line-height: 190%; + color: @color-report-widget-description; + } + + a:not(.btn) { + color: @color-report-widget-link; + text-decoration: none; + &:hover { + color: @link-color; + text-decoration: none; + } + } + + p.flash-message.static { + margin-bottom: 0; + } + + .icon-circle { + &.success { color: @brand-success; } + &.primary { color: @brand-primary; } + &.warning { color: @brand-warning; } + &.danger { color: @brand-danger; } + &.info { color: @brand-info; } + } +} \ No newline at end of file diff --git a/modules/backend/assets/less/controls/scrollbar.less b/modules/backend/assets/less/controls/scrollbar.less new file mode 100644 index 0000000..d4966e5 --- /dev/null +++ b/modules/backend/assets/less/controls/scrollbar.less @@ -0,0 +1,125 @@ +// +// Scrollbar +// -------------------------------------------------- + +.drag-noselect { + .user-select(none); +} + +@scrollbar-thumb-size: 6px; + +.control-scrollbar { + position: relative; + overflow: hidden; + height: 100%; + + >.scrollbar-scrollbar { + position: absolute; + z-index: 100; + .scrollbar-track { + background-color: @color-scrollbar-track; + position: relative; + .border-radius(5px); + + .scrollbar-thumb { + background-color: @color-scrollbar-thumb; + .border-radius(5px); + cursor: pointer; + overflow: hidden; + position: absolute; + } + } + + &.disabled { + display: none !important; + } + } + + &.vertical { + >.scrollbar-scrollbar { + right: 0; + margin-right: 5px; + width: @scrollbar-thumb-size; + .scrollbar-track { + height: 100%; + width: @scrollbar-thumb-size; + .scrollbar-thumb { + height: 20px; + width: @scrollbar-thumb-size; + top: 0; + left: 0; + } + } + + &:active, &:hover { + width: @scrollbar-thumb-size + 2px; + .transition(width .3s); + .scrollbar-track, + .scrollbar-thumb { + width: @scrollbar-thumb-size + 2px; + .transition(width .3s); + } + } + } + } + + &.horizontal { + >.scrollbar-scrollbar { + margin: 0 0 5px; + clear: both; + height: @scrollbar-thumb-size; + .scrollbar-track { + width: 100%; + height: @scrollbar-thumb-size; + .scrollbar-thumb { + height: @scrollbar-thumb-size; + margin: 2px 0; + left: 0; + top: 0; + } + } + + &:active, &:hover { + height: @scrollbar-thumb-size + 2px; + .transition(height .3s); + .scrollbar-track, + .scrollbar-thumb { + height: @scrollbar-thumb-size + 2px; + .transition(height .3s); + } + } + } + } +} + +html.mobile { + .control-scrollbar { + overflow: auto; + -webkit-overflow-scrolling: touch; + } +} + +.no-touch .control-scrollbar { + >.scrollbar-scrollbar { + opacity: 0; + .transition(opacity 0.3s); + } + + &:active >.scrollbar-scrollbar, + &:hover >.scrollbar-scrollbar {opacity: 1;} +} + +@media (max-width: @screen-sm) { + &.responsive-sidebar { + > .layout-cell:last-child { + .control-scrollbar { + overflow: visible; + height: auto; + + .scrollbar-scrollbar { + display: none!important; + } + } + } + } +} diff --git a/modules/backend/assets/less/controls/scrollpad.less b/modules/backend/assets/less/controls/scrollpad.less new file mode 100644 index 0000000..a364d54 --- /dev/null +++ b/modules/backend/assets/less/controls/scrollpad.less @@ -0,0 +1,98 @@ +.scrollpad-scrollbar-size-tester { + width: 50px; + height: 50px; + overflow-y: scroll; + position: absolute; + top: -200px; + left: -200px; + + div { + height: 100px; + } + + &::-webkit-scrollbar { + width: 0; + height: 0; + } +} + +div.control-scrollpad { + position: relative; + width: 100%; + height: 100%; + overflow: hidden; + + > div { + overflow: hidden; + overflow-y: scroll; + height: 100%; + + &::-webkit-scrollbar { + width: 0; + height: 0; + } + } + + &[data-direction=horizontal] > div { + overflow-x: scroll; + overflow-y: hidden; + width: 100%; + + &::-webkit-scrollbar { + width: auto; + height: 0; + } + } + + > .scrollpad-scrollbar { + z-index: 199; // Be careful here + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 11px; + background-color: @color-scrollbar-track; + opacity: 0; + overflow: hidden; + .border-radius(5px); + .transition(opacity 0.3s); + + .drag-handle { + position: absolute; + right: 2px; + min-height: 10px; + width: 7px; + background-color: @color-scrollbar-thumb; + .border-radius(5px); + } + + &:hover { + .opacity(.7); + .transition(opacity 0 linear); + } + + &[data-visible] { + .opacity(.7); + } + + &[data-hidden] { + display: none; + } + } + + &[data-direction=horizontal] > .scrollpad-scrollbar { + top: auto; + left: 0; + width: auto; + height: 11px; + + .drag-handle { + right: auto; + top: 2px; + height: 7px; + min-height: 0; + min-width: 10px; + width: auto; + } + } +} \ No newline at end of file diff --git a/modules/backend/assets/less/controls/selector-group.less b/modules/backend/assets/less/controls/selector-group.less new file mode 100644 index 0000000..4651cdb --- /dev/null +++ b/modules/backend/assets/less/controls/selector-group.less @@ -0,0 +1,35 @@ +.nav.selector-group { + font-size: 13px; + letter-spacing: 0.01em; + margin-bottom: 20px; + + li { + a { + padding: 7px 20px 7px 23px; + color: #95a5a6; + } + + &.active { + border-left: 3px solid #e6802b; + padding-left: 0; + + a { + padding-left: 20px; + color: #2b3e50; + } + } + + i[class^="icon-"] { + font-size: 17px; + margin-right: 6px; + position: relative; + top: 1px; + } + } +} + +div.panel { + .nav.selector-group { + margin: 0 -20px 20px -20px; + } +} \ No newline at end of file diff --git a/modules/backend/assets/less/controls/sidenav-tree.less b/modules/backend/assets/less/controls/sidenav-tree.less new file mode 100644 index 0000000..334eecb --- /dev/null +++ b/modules/backend/assets/less/controls/sidenav-tree.less @@ -0,0 +1,270 @@ +.sidenav-tree { + width: 300px; + + .control-toolbar { + padding: 0; + + .toolbar-item { + display: block; + } + + input.form-control { + border: none; + outline: none; + padding: 12px 13px 13px; + .border-radius(0); + .box-shadow(inset -3px 0 3px rgba(0,0,0,0.1)); + + &.search { + background-position: right -78px; + } + } + } + + ul { + padding: 0; + margin: 0; + list-style: none; + } + + div.scrollbar-thumb { + background: rgba(0,0,0,.2) !important; + } + + ul.top-level > li { + &[data-status=collapsed] { + > div.group { + h3:before { + .transform(~'rotate(0deg) translate(2px, -2px)'); + } + + // Hide triangle + &:before, &:after { + display: none; + } + } + + ul { + display: none; + } + } + + > div.group { + position: relative; + + h3 { + background: @color-sidebarnav-tree-group-bg; + color: @color-sidebarnav-tree-group; + text-transform: uppercase; + font-size: 15px; + padding: 15px 15px 15px 40px; + margin: 0; + position: relative; + cursor: pointer; + font-weight: 400; + + &:before { + display: block; + position: absolute; + width: 10px; + height: 10px; + left: 16px; + top: 15px; + color: @color-list-arrow; + .icon(@angle-right); + .transform(~'rotate(90deg) translate(5px, -3px)'); + .transition(all 0.1s ease); + font-size: 16px; + } + } + + // Use two triangles to achieve the darkening effect + &:before, + &:after { + .triangle(down, 15px, 8px, @brand-primary); + position: absolute; + left: 15px; + bottom: -8px; + z-index: 101; + } + + &:after { + .triangle(down, 15px, 8px, @color-sidebarnav-tree-group-bg); + } + } + + > ul { + li { + + a { + display: block; + position: relative; + padding: 18px 25px 18px 55px; + background: @color-sidebarnav-tree-inactive-bg; + border-bottom: 1px solid @color-sidebarnav-tree-group-bg; + color: @color-sidebarnav-tree-inactive-text; + text-decoration: none !important; + .opacity(.65); + + &:active, + &:hover { + .opacity(1); + text-decoration: none; + } + + i { + position: absolute; + left: 16px; + top: 18px; + font-size: 22px; + } + + span { + display: block; + line-height: 150%; + + &.header { + color: @color-sidebarnav-tree-inactive-header; + font-size: @font-size-base + 1; + margin-bottom: 5px; + } + + &.description { + color: @color-sidebarnav-tree-inactive-desc; + font-size: @font-size-base - 1; + } + } + } + + &:hover a, + &.active a { + .opacity(1); + } + + &.active { + border-left: 5px solid @brand-secondary; + + a { + color: @color-sidebarnav-tree-active-text; + padding-right: 20px; + + span.header { + color: @color-sidebarnav-tree-active-header; + } + + span.description { + color: @color-sidebarnav-tree-active-text; + } + } + } + + // &:last-child a { + // border-bottom: none; + // } + } + } + } + + .back-link { + display: none; + } +} + +@media (min-width: @screen-sm-min) { + .sidenav-tree-root .sidenav-tree { + width: 600px; + + ul.top-level > li > ul { + font-size: 0; + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: flex-start; + align-items: stretch; + align-content: stretch; + + > li { + display: inline-block; + // flex-grow: 1; + width: 300px; + + a { + height: 100%; + } + } + } + } +} + +@media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) { + .sidenav-tree-root .sidenav-tree { + width: 100%; + + ul.top-level > li > ul > li { + width: 50%; + } + } +} + +@media (min-width: @screen-lg-min) { + .sidenav-tree-root .sidenav-tree { + width: 900px; + } +} + +@media (max-width: @screen-sm) { + .sidenav-tree { + width: 100%; + height: auto !important; + display: block !important; + + > .layout { + display: none; + } + } + + .sidenav-tree-root { + .sidenav-tree { + width: 100% !important; + height: 100% !important; + display: table-cell !important; + + .back-link { + display: none !important; + } + + > .layout { + display: table !important; + } + } + + #layout-body { + display: none; + } + } + + body.has-sidenav-tree { + .sidenav-tree { + .back-link { + display: block; + padding: 13px 15px; + background: @color-sidebarnav-back-link-bg; + color: @color-sidebarnav-back-link-text; + font-size: 14px; + line-height: 14px; + text-transform: uppercase; + i { + display: inline-block; + margin-right: 10px; + } + &:hover { + text-decoration: none; + } + } + } + + #layout-body { + display: block !important; + } + } +} diff --git a/modules/backend/assets/less/controls/simplelist.less b/modules/backend/assets/less/controls/simplelist.less new file mode 100644 index 0000000..355ff28 --- /dev/null +++ b/modules/backend/assets/less/controls/simplelist.less @@ -0,0 +1,265 @@ +// +// Simple List +// -------------------------------------------------- +// Usage (bullets): +//
+//
    +//
  • Hello friend
  • +//
+//
+// +// With icons (no bullets): +//
+//
    +//
  • Hello friend
  • +//
+//
+// +// With checkboxes: +//
+//
    +//
  • +//
    +// +// +//
    +//
  • +//
+//
+// +// Divided (basic): +//
+//
    +//
  • Hello friend
  • +//
+//
+// +// Selectable: +// +// +// Selectable (box): +// +// + +.control-simplelist { + font-size: 13px; + padding: 20px 20px 2px 20px; + margin-bottom: @padding-standard; + background: @color-form-checkboxlist-background; + .border-radius(@border-radius-base); + + ul { padding-left: 15px; } + + &.form-control { + ul { margin-bottom: 0; } + li { + padding-top: 5px; + padding-bottom: 5px; + } + } + + &.with-icons, + &.with-checkboxes, + &.is-divided, + &.is-selectable { + ul { + list-style-type: none; + padding-left: 0; + } + } + + &.with-checkboxes { + li { + margin-top: -5px; + + &:first-child { + margin-top: 0; + } + + &:last-child { + div.custom-checkbox { + margin-bottom: 0; + + label { + margin-bottom: 5px; + } + } + } + } + } + + &.is-sortable { + + li.placeholder { + position: relative; + &:before { + top: -10px; + position: absolute; + .triangle(right, 5px, 9px, @color-sortable-caret); + } + } + + li.dragged { + position: absolute; + .opacity(.5); + z-index: 2000; + color: @color-sortable-active; + + width: auto !important; // Prevent browser scrollbars + } + } + + &.is-scrollable { + height: 200px; + &.size-tiny { min-height: @size-tiny + 200; } + &.size-small { min-height: @size-small + 200; } + &.size-large { min-height: @size-large + 200; } + &.size-huge { min-height: @size-huge + 200; } + &.size-giant { min-height: @size-giant + 200; } + } + + &.is-divided, + &.is-selectable, + &.is-selectable-box { + padding: 0; + + li { + .heading { + font-size: 14px; + font-weight: 500; + } + + .description {} + } + } + + &.is-divided, + &.is-selectable { + li { + padding: 5px 10px; + border-bottom: 1px solid @color-list-border; + + &:last-child { + border-bottom: none; + } + } + } + + &.is-selectable { + li { + a { + padding: 5px 10px; + margin: -5px -10px; + display: block; + color: @text-color; + } + &:hover { + background: @color-list-hover-bg; + cursor: pointer; + &, a { color: white; } + a { text-decoration: none; } + } + + &.active { + a { + background: #f0f0f0; + &:hover { + background: @color-list-hover-bg; + } + } + } + } + } + + &.is-selectable-box { + padding-top: 15px; + margin-bottom: 0; + + li { + width: 155px; + margin: 8px; + display: inline-block; + text-align: center; + vertical-align: top; + + a { + text-decoration: none; + display: block; + color: @text-color; + + .box { + display: block; + width: 155px; + height: 155px; + border: 3px solid rgba(0,0,0,.1); + position: relative; + .transition(border .3s ease); + } + + .image { + display: block; + width: 56px; + height: 56px; + position: absolute; + top: 50%; + left: 50%; + margin-top: -28px; + margin-left: -28px; + + > i { + font-size: 56px; + color: rgba(0,0,0,.25); + } + } + + .heading { + margin: 7px 0; + padding: 0; + } + + .description { + font-size: 12px; + } + + &:hover { + .box { + border-color: rgba(0,0,0,.2); + } + + .image > i { + color: rgba(0,0,0,.45); + } + } + } + } + } +} + +.list-preview .control-simplelist { + &.is-selectable { + ul { + margin-bottom: 0; + } + } +} diff --git a/modules/backend/assets/less/controls/svg-icons.less b/modules/backend/assets/less/controls/svg-icons.less new file mode 100644 index 0000000..6e82b89 --- /dev/null +++ b/modules/backend/assets/less/controls/svg-icons.less @@ -0,0 +1,33 @@ +.svg-icon-container { + img.svg-icon { + // SVG icons are invisible until SVG support is detected + // with JavaScript to reduce flickering on page load. + // This should be overridden in a specific control, + // inside html.svg {} + display: none; + } + + &.svg-active-effects { + img.svg-icon { + -webkit-filter: grayscale(100%); + filter: grayscale(100%); + .opacity(0.6); + } + + &:hover, &.active { + img.svg-icon { + -webkit-filter: none; + filter: none; + .opacity(1); + } + } + } +} + +html.svg { + .svg-icon-container { + i.svg-replace { + display: none; + } + } +} diff --git a/modules/backend/assets/less/controls/tree-path.less b/modules/backend/assets/less/controls/tree-path.less new file mode 100644 index 0000000..c2422be --- /dev/null +++ b/modules/backend/assets/less/controls/tree-path.less @@ -0,0 +1,61 @@ +ul.tree-path { + list-style: none; + padding: 0; + margin-bottom: 0; + + li { + display: inline-block; + margin-right: 1px; + font-size: 13px; + + &:after { + .icon(@angle-right); + display: inline-block; + font-size: 13px; + margin-left: 5px; + position: relative; + top: 1px; + color: #95a5a6; + } + + &:last-child { + a { + cursor: default; + } + + &:after { + display: none; + } + } + + &.go-up { + font-size: 12px; + margin-right: 7px; + + a { + color: #95a5a6; + + &:hover { + color: @link-color; + } + } + + &:after { + display: none; + } + } + + &.root a { + font-weight: 600; + color: #405261; + } + + a { + color: #95a5a6; + + &:hover { + text-decoration: none; + } + } + } +} \ No newline at end of file diff --git a/modules/backend/assets/less/controls/treelist.less b/modules/backend/assets/less/controls/treelist.less new file mode 100644 index 0000000..b0dfec8 --- /dev/null +++ b/modules/backend/assets/less/controls/treelist.less @@ -0,0 +1,93 @@ +// +// Tree List +// -------------------------------------------------- + +.control-treelist { + ol { + padding: 0; + margin: 0; + list-style: none; + + ol { + margin: 0; + margin-left: 15px; + padding-left: 15px; + border-left: 1px solid #dbdee0; + } + } + + > ol > li > div.record:before { + display: none; + } + + li { + margin: 0; + padding: 0; + > div.record { + margin: 0; + font-size: 12px; + margin-bottom: 5px; + position: relative; + display: block; + + &:before { + color: #bdc3c7; + .icon(@circle); + font-size: 6px; + position: absolute; + left: -18px; + top: 11px; + } + + > a.move { + display: inline-block; + padding: 7px 0 7px 10px; + text-decoration: none; + color: #bdc3c7; + &:hover { + color: @color-list-hover-bg; + } + &:before { .icon(@bars); } + } + > span { + color: @color-list-text; + display: inline-block; + padding: 7px 15px 7px 5px; + } + } + + &.dragged { + position: absolute; + z-index: 2000; + width: auto !important; // Prevent browser scrollbars + height: auto !important; + > div.record { + .opacity(.5); + background: @color-list-hover-bg !important; + > a.move:before, > span { color: white; } + + &:before { + display: none; + } + } + } + + &.placeholder { + display: inline-block; + position: relative; + background: @color-list-hover-bg !important; + height: 25px; + margin-bottom: 5px; + &:before { + display: block; + position: absolute; + .icon(@chevron-left); + color: #d35714; + left: -10px; + top: 8px; + z-index: 2000; + } + } + + } +} diff --git a/modules/backend/assets/less/controls/treeview.less b/modules/backend/assets/less/controls/treeview.less new file mode 100644 index 0000000..c9da29a --- /dev/null +++ b/modules/backend/assets/less/controls/treeview.less @@ -0,0 +1,630 @@ +.control-treeview { + margin-bottom: 40px; + + .no-data() { + padding: 18px 0; + margin: 0; + color: @color-filelist-norecords-text; + font-size: @font-size-base; + text-align: center; + font-weight: 400; + } + + ol { + margin: 0; + padding: 0; + list-style: none; + background: @color-treeview-item-bg; + + > li { + .transition(width 1s); + + > div { + font-size: @font-size-base; + font-weight: normal; + background: @color-treeview-item-bg; + border-bottom: 1px solid @color-panel-light; + position: relative; + + > a { + color: @color-treeview-item-title; + padding: 11px 45px 10px 61px; + display: block; + line-height: 150%; + text-decoration: none; + .box-sizing(border-box); + } + + &:before { + content: ' '; + background-image: url(../images/treeview-icons.png); + background-position: 0px -28px; + background-repeat: no-repeat; + background-size: 42px auto; + + position: absolute; + width: 21px; + height: 22px; + left: 28px; + top: 15px; + } + + span.comment { + display: block; + font-weight: 400; + color: @color-treeview-item-comment; + font-size: @font-size-base - 1; + margin-top: 2px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + > span.expand { + .hide-text(); + display: none; + position: absolute; + width: 20px; + height: 20px; + top: 19px; + left: 2px; + cursor: pointer; + color: @color-treeview-control; + .transition(transform 0.1s ease); + + &:before { + .icon(@caret-right); + line-height: 100%; + font-size: @font-size-base + 1; + + position: relative; + left: 8px; + top: 2px; + } + } + + > span.drag-handle { + .hide-text(); + .transition(opacity 0.4s); + + position: absolute; + right: 9px; + bottom: 0; + width: 18px; + height: 19px; + cursor: move; + color: @color-treeview-control; + .opacity(0); + + &:before { + .icon(@bars); + font-size: 18px; + } + } + + span.borders { + font-size: 0; + } + + > ul.submenu { + position: absolute; + left: 20px; + bottom: -36.9px; + padding: 0; + list-style: none; + z-index: 200; + height: 37px; + display: none; + margin-left: 15px; + + background: transparent url(../images/treeview-submenu-tabs.png) repeat-x left -39px; + + &:before, &:after { + background: transparent url(../images/treeview-submenu-tabs.png) no-repeat left top; + content: ' '; + display: block; + width: 20px; + height: 37px; + position: absolute; + top: 0; + } + + &:before { + left: -20px; + } + + &:after { + background-position: -100px top; + right: -20px; + } + + li { + font-size: @font-size-base - 2; + + a { + display: block; + padding: 4px 3px 0 3px; + color: @color-treeview-submenu-text; + text-decoration: none; + outline: none; + + i { + margin-right: 5px; + } + } + } + } + + &:hover { + > ul.submenu { + display: block; + } + } + + &:active { + > ul.submenu { + background-position: left -116px; + + &:before { + background-position: left -77px; + } + &:after { + background-position: -100px -77px; + } + } + } + + .checkbox { + position: absolute; + top: -2px; + right: 0; + + label { + margin-right: 0; + + &:before { + border-color: @color-filelist-cb-border; + } + } + } + + &.popover-highlight { + background-color: @color-treeview-hover-bg !important; + + &:before { + background-position: 0px -80px; + } + + > a { + color: @color-treeview-hover-text !important; + cursor: default; + } + + span { + color: @color-treeview-hover-text !important; + } + + > ul.submenu, > span.drag-handle { + display: none!important; + } + } + } + + &.dragged div, > div:hover { + background-color: @color-treeview-hover-bg !important; + + > a { + color: @color-treeview-hover-text !important; + } + + &:before { + background-position: 0px -80px; + } + + &:after { + top: 0 !important; + bottom: 0 !important; + } + + span { + color: @color-treeview-hover-text !important; + + &.drag-handle { + cursor: move; + .opacity(1); + } + + &.borders { + display: none; + } + } + } + + > div:active { + background-color: @color-treeview-active-bg !important; + + > a { + color: @color-treeview-active-text !important; + } + } + + &[data-no-drag-mode] div:hover { + span.drag-handle { + cursor: default!important; + .opacity(.3)!important; + } + } + + &.dragged { + li.has-subitems, &.has-subitems { + > div:before { + background-position: 0px -52px; + } + } + + div > ul.submenu { + display: none!important; + } + } + + > ol { + padding-left: 20px; + padding-right: 20px; + } + + &[data-status=collapsed] > ol { + display: none; + } + + &.has-subitems { + > div { + &:before { + background-position: 0 0; + width: 23px; + height: 26px; + left: 26px; + } + + &:hover, &.popover-highlight { + &:before { background-position: 0px -52px; } + } + + span.expand { + display: block; + } + } + } + + &.placeholder { + position: relative; + .opacity(.5); + + ol { + display: none; + } + } + + &.dragged { + position: absolute; + z-index: 2000; + .opacity(.25); + + > div { + .border-radius(3px); + } + + ol { + display: none; + } + } + + &.drop-target { + > div { + background-color: #2581b8!important; + + > a { + color: @color-treeview-hover-text; + > span.comment { + color: @color-treeview-hover-text; + } + } + + &:before { + background-position: 0px -80px; + } + } + + &.has-subitems > div:before { + background-position: 0px -52px; + } + } + + &[data-status=expanded] > div > span.expand { + .transform( ~'rotate(90deg) translate(0, 0)' ); + } + + &.drag-ghost { + background-color: transparent; + box-sizing: content-box; + } + + &.active { + > div { + background: @color-list-active; + + &:after { + position: absolute; + width: 4px; + left: 0; + top: -1px; + bottom: -1px; + background: @color-list-active-border; + display: block; + content: ' '; + } + + > span.comment, > span.expand { + color: @color-treeview-item-active-comment; + } + + > span.borders { + &:before, &:after { + content: ' '; + position: absolute; + width: 100%; + height: 1px; + display: block; + left: 0; + background-color: @color-list-active; + } + + &:before {top: -1px;} + &:after {bottom: -1px;} + } + } + } + + &.no-data { + .no-data(); + } + } + + @max-level: 10; + + .tree-view-paddings (@level) when (@level > 0) { + > li { + > ol { + > li > div { + margin-left: -20-(@max-level - @level)*20px; + margin-right: -20-(@max-level - @level)*20px; + padding-left: 61+(@max-level - @level + 1)*10px; + + > a { + margin-left: -61-(@max-level - @level + 1)*10px; + padding-left: 61+(@max-level - @level + 1)*10px; + } + + &:before { + margin-left: (@max-level - @level + 1)*10px; + } + + > span.expand { + left: 2+(@max-level - @level + 1)*10px; + } + } + + .tree-view-paddings(@level - 1); + } + } + } + + .tree-view-paddings (@max-level); + } + + p.no-data { + .no-data(); + } + + a.menu-control { + display: block; + margin: 20px; + padding: 13px 15px; + border: dotted 2px #ebebeb; + color: #bdc3c7; + font-size: @font-size-base - 2; + font-weight: 600; + text-transform: uppercase; + border-radius: 5px; + vertical-align: middle; + + &:hover, &:focus { + text-decoration: none; + background-color: @color-treeview-hover-bg; + color: @color-treeview-hover-text; + border: none; + padding: 15px 17px; + } + + &:active { + background: @color-treeview-active-bg; + color: @color-treeview-active-text; + } + + i { + margin-right: 10px; + font-size: 14px; + } + } + + /* + * Light version of the treeview - transparent background, no bottom borders, + * smaller paddings, inline submenu + */ + &.treeview-light { + margin-bottom: 0; + margin-top: 20px; + + ol { + background-color: transparent; + > li { + > div { + background-color: transparent; + border-bottom: none; + + &:before { + top: 15px; + } + + > a { + padding-top: 10px; + padding-bottom: 10px; + } + + span.expand { + top: 19px; + } + + > span.drag-handle { + top: 0; + right: 0; + bottom: auto; + height: 100%; + width: 60px; + background: @color-treeview-light-submenu-bg; + .transition(none)!important; + + &:before { + position: absolute; + left: 50%; + top: 50%; + margin-left: -6px; + } + } + + > ul.submenu { + right: 60px; + left: auto; + bottom: auto; + top: 0; + height: 100%; + margin: 0; + background: transparent; + white-space: nowrap; + font-size: 0; + + &:before, &:after { + display: none; + } + + li { + height: 100%; + display: inline-block; + background: @color-treeview-light-submenu-bg; + border-right: 1px solid @color-treeview-light-submenu-border; + + p { + display: table; + height: 100%; + padding: 0; + margin: 0; + + a { + display: table-cell; + vertical-align: middle; + height: 100%; + padding: 0 20px; + font-size: @font-size-base - 1; + .box-sizing(border-box); + + i.control-icon { + font-size: 22px; + margin-right: 0; + } + } + } + } + } + } + } + } + } +} + +// +// Sorting guides +// + +body.dragging .control-treeview { + ol.dragging, ol.dragging ol { + background: #ccc; + padding-right: 0; + + > li { + > div { + margin-right: 0; + .transition(margin 1s); + + .custom-checkbox { + .transition(opacity .5s); + .opacity(0); + } + } + } + } + + &.treeview-light { + ol.dragging, ol.dragging ol { + > li > div { + background-color: #f9f9f9; + } + } + } +} + +// +// Retina +// + +@media only screen and (min--moz-device-pixel-ratio: 1.5), only screen and (-o-min-device-pixel-ratio: 3/2), only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-devicepixel-ratio: 1.5), only screen and (min-resolution: 1.5dppx) { + .control-treeview { + ol { + > li { + > div{ + &:before { + background-position: 0px -79px; + background-size: 21px auto; + } + } + + &.has-subitems > div { + &:before {background-position: 0px -52px;} + &:hover, &.popover-highlight { + &:before {background-position: 0px -102px;} + } + } + + &.dragged > div, &.dragged li > div, > div:hover, > div.popover-highlight { + &:before {background-position: 0px -129px;} + } + + &.dragged { + li.has-subitems, &.has-subitems { + > div:before { + background-position: 0px -102px; + } + } + } + + &.drop-target { + > div:before { + background-position: 0px -129px; + } + + &.has-subitems > div:before { + background-position: 0px -102px; + } + } + } + } + } +} diff --git a/modules/backend/assets/less/core/animations.less b/modules/backend/assets/less/core/animations.less new file mode 100644 index 0000000..c0f7fe0 --- /dev/null +++ b/modules/backend/assets/less/core/animations.less @@ -0,0 +1,363 @@ +// +// Fade In +// + +@-webkit-keyframes fadeIn { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +@keyframes fadeIn { + 0% { + opacity: 0; + } + + 100% { + opacity: 1; + } +} + +.fadeIn { + -webkit-animation-name: fadeIn; + animation-name: fadeIn; +} + +// +// Fade In Down +// + +@-webkit-keyframes fadeInDown { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes fadeInDown { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + -ms-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + -ms-transform: none; + transform: none; + } +} + +.fadeInDown { + -webkit-animation-name: fadeInDown; + animation-name: fadeInDown; +} + +// +// Fade In Left +// + +@-webkit-keyframes fadeInLeft { + 0% { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes fadeInLeft { + 0% { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + -ms-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + -ms-transform: none; + transform: none; + } +} + +.fadeInLeft { + -webkit-animation-name: fadeInLeft; + animation-name: fadeInLeft; +} + +// +// Fade In Right +// + +@-webkit-keyframes fadeInRight { + 0% { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes fadeInRight { + 0% { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + -ms-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + -ms-transform: none; + transform: none; + } +} + +.fadeInRight { + -webkit-animation-name: fadeInRight; + animation-name: fadeInRight; +} + +// +// Fade In Up +// + +@-webkit-keyframes fadeInUp { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +@keyframes fadeInUp { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + -ms-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + -ms-transform: none; + transform: none; + } +} + +.fadeInUp { + -webkit-animation-name: fadeInUp; + animation-name: fadeInUp; +} + +@-webkit-keyframes fadeInUpBig { + 0% { + opacity: 0; + -webkit-transform: translate3d(0, 2000px, 0); + transform: translate3d(0, 2000px, 0); + } + + 100% { + opacity: 1; + -webkit-transform: none; + transform: none; + } +} + +// +// Fade Out +// + +@-webkit-keyframes fadeOut { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +@keyframes fadeOut { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +} + +.fadeOut { + -webkit-animation-name: fadeOut; + animation-name: fadeOut; +} + +// +// Fade Out Down +// + +@-webkit-keyframes fadeOutDown { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +@keyframes fadeOutDown { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, 100%, 0); + -ms-transform: translate3d(0, 100%, 0); + transform: translate3d(0, 100%, 0); + } +} + +.fadeOutDown { + -webkit-animation-name: fadeOutDown; + animation-name: fadeOutDown; +} + +// +// Fade Out Left +// + +@-webkit-keyframes fadeOutLeft { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +@keyframes fadeOutLeft { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(-100%, 0, 0); + -ms-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +.fadeOutLeft { + -webkit-animation-name: fadeOutLeft; + animation-name: fadeOutLeft; +} + +// +// Fade Out Right +// + +@-webkit-keyframes fadeOutRight { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +@keyframes fadeOutRight { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(100%, 0, 0); + -ms-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +.fadeOutRight { + -webkit-animation-name: fadeOutRight; + animation-name: fadeOutRight; +} + +// +// Fade Out Up +// + +@-webkit-keyframes fadeOutUp { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +@keyframes fadeOutUp { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + -webkit-transform: translate3d(0, -100%, 0); + -ms-transform: translate3d(0, -100%, 0); + transform: translate3d(0, -100%, 0); + } +} + +.fadeOutUp { + -webkit-animation-name: fadeOutUp; + animation-name: fadeOutUp; +} diff --git a/modules/backend/assets/less/core/boot.less b/modules/backend/assets/less/core/boot.less new file mode 100644 index 0000000..659749e --- /dev/null +++ b/modules/backend/assets/less/core/boot.less @@ -0,0 +1,11 @@ +// +// Boots the Core LESS +// +// Includes non-output LESS files such as mixins and variables +// + +// Core variables and mixins +@import "../../../../system/assets/ui/less/global.less"; + +@import "variables.less"; +@import "mixins.less"; diff --git a/modules/backend/assets/less/core/mixins.less b/modules/backend/assets/less/core/mixins.less new file mode 100644 index 0000000..e3e0d69 --- /dev/null +++ b/modules/backend/assets/less/core/mixins.less @@ -0,0 +1,165 @@ +// -------------------------------------------------- +// Flexbox LESS mixins +// The spec: http://www.w3.org/TR/css3-flexbox +// -------------------------------------------------- + +// Flexbox display +// flex or inline-flex +.flex-display() { + display: ~"-webkit-box"; + display: ~"-webkit-flex"; + display: ~"-moz-flex"; + display: ~"-ms-flexbox"; // IE10 uses -ms-flexbox + display: ~"-ms-flex"; // IE11 + display: flex; +} + +// The 'flex: 0 0 auto' shorthand +.flex-fix() { + -webkit-box-flex: 0; + -webkit-flex: 0 0 auto; + -moz-flex: 0 0 auto; + -ms-flex: 0 0 auto; + flex: 0 0 auto; +} + +// The 'flex: 1 1 auto' shorthand +.flex-stretch() { + -webkit-box-flex: 1; + -webkit-flex: 1 1 auto; + -moz-flex: 1 1 auto; + -ms-flex: 1 1 auto; + flex: 1 1 auto; +} + +// The 'flex: 1' shorthand +.flex-stretch-constrain() { + -webkit-box-flex: 1; + -webkit-flex: 1; + -moz-flex: 1; + -ms-flex: 1; + flex: 1; +} + +// Flex Flow Direction Column +// - applies to: flex containers +.flex-direction-column() { + -webkit-flex-direction: column; + -moz-flex-direction: column; + -webkit-box-orient: vertical; + -ms-flex-direction: column; + flex-direction: column; +} + +// Flex Flow Direction Row +// - applies to: flex containers +.flex-direction-row() { + -webkit-flex-direction: row; + -moz-flex-direction: row; + -webkit-box-orient: horizontal; + -ms-flex-direction: row; + flex-direction: row; +} + +// Flex Line Wrapping +// - applies to: flex containers +// nowrap | wrap | wrap-reverse +.flex-wrap(@wrap: nowrap) { + -webkit-flex-wrap: @wrap; + -moz-flex-wrap: @wrap; + -ms-flex-wrap: @wrap; + flex-wrap: @wrap; +} + +// Flex Direction and Wrap +// - applies to: flex containers +// || +.flex-flow(@flow) { + -webkit-flex-flow: @flow; + -moz-flex-flow: @flow; + -ms-flex-flow: @flow; + flex-flow: @flow; +} + +// Display Order +// - applies to: flex items +// +.flex-order(@order: 0) { + -webkit-order: @order; + -moz-order: @order; + -ms-order: @order; + order: @order; +} + +// Flex grow factor +// - applies to: flex items +// +.flex-grow(@grow: 0) { + -webkit-flex-grow: @grow; + -moz-flex-grow: @grow; + -ms-flex-grow: @grow; + flex-grow: @grow; +} + +// Flex shr +// - applies to: flex itemsink factor +// +.flex-shrink(@shrink: 1) { + -webkit-flex-shrink: @shrink; + -moz-flex-shrink: @shrink; + -ms-flex-shrink: @shrink; + flex-shrink: @shrink; +} + +// Flex basis +// - the initial main size of the flex item +// - applies to: flex itemsnitial main size of the flex item +// +.flex-basis(@width: auto) { + -webkit-flex-basis: @width; + -moz-flex-basis: @width; + -ms-flex-basis: @width; + flex-basis: @width; +} + +// Axis Alignment +// - applies to: flex containers +// flex-start | flex-end | center | space-between | space-around +.justify-content(@justify: flex-start) { + -webkit-justify-content: @justify; + -moz-justify-content: @justify; + -ms-justify-content: @justify; + -webkit-box-pack: @justify; + justify-content: @justify; +} + +// Packing Flex Lines +// - applies to: multi-line flex containers +// flex-start | flex-end | center | space-between | space-around | stretch +.align-content(@align: stretch) { + -webkit-align-content: @align; + -moz-align-content: @align; + -webkit-box-align: @align; + -ms-align-content: @align; + align-content: @align; +} + +// Cross-axis Alignment +// - applies to: flex containers +// flex-start | flex-end | center | baseline | stretch +.align-items(@align: stretch) { + -webkit-align-items: @align; + -moz-align-items: @align; + -ms-align-items: @align; + align-items: @align; +} + +// Cross-axis Alignment +// - applies to: flex items +// auto | flex-start | flex-end | center | baseline | stretch +.align-self(@align: auto) { + -webkit-align-self: @align; + -moz-align-self: @align; + -ms-align-self: @align; + align-self: @align; +} \ No newline at end of file diff --git a/modules/backend/assets/less/core/variables.less b/modules/backend/assets/less/core/variables.less new file mode 100644 index 0000000..5ade13a --- /dev/null +++ b/modules/backend/assets/less/core/variables.less @@ -0,0 +1,153 @@ +// +// Override UI variables +// -------------------------------------------------- + +@font-family-base: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; + +// +// Paths +// -------------------------------------------------- + +@type-font-path: "../font"; + +// +// Colors +// -------------------------------------------------- + +@color-border: #cccccc; +@color-border-light: #e1e1e1; + +@color-mainmenu: #151515; +@color-mainmenu-inactive: rgba(255,255,255,.6); +@color-mainmenu-active: #ffffff; +@color-mainmenu-active-bg: #262626; +@color-mainmenu-collapsed: #000000; + +@color-accountmenu-bg: #f9f9f9; +@color-accountmenu-text: #666666; +@color-accountmenu-divider: #e0e0e0; + +@color-footer: rgba(255,255,255,.8); +@color-footer-border: #dfdfdf; +@color-footer-text: #666666; + +@color-sidebarnav-active-text: #ffffff; +@color-sidebarnav-active-icon: #ffffff; +@color-sidebarnav-inactive-text: rgba(255,255,255,.6); +@color-sidebarnav-inactive-icon: rgba(255,255,255,.6); +@color-sidebarnav-counter-bg: #d9350f; +@color-sidebarnav-counter-text: #ffffff; + +@color-sidebarnav-tree-group: #ecf0f1; +@color-sidebarnav-tree-group-bg: rgba(0,0,0,.15); +@color-sidebarnav-tree-inactive-header: #ffffff; +@color-sidebarnav-tree-inactive-desc: rgba(255,255,255,.6); +@color-sidebarnav-tree-inactive-text: #ffffff; +@color-sidebarnav-tree-active-header: #ffffff; +@color-sidebarnav-tree-inactive-bg: transparent; +@color-sidebarnav-tree-active-text: rgba(255,255,255,.91); +@color-sidebarnav-tree-active-marker: @brand-secondary; +@color-sidebarnav-back-link-bg: #2b3e50; +@color-sidebarnav-back-link-text: #bdc3c7; + +@color-scrollbar-track: transparent; +@color-scrollbar-thumb: rgba(0,0,0,.35); +@color-scrollpanel-border: #efefef; +@color-scrollpanel-fix-button: #aaaaaa; +@color-scrollpanel-fix-button-light: #eeeeee; +@color-scroll-indicator: #bbbbbb; + +@color-panel-light: #ECF0F1; + +@color-outer-muted-text: rgba(255,255,255,.44); +@color-outer-heading: #feffff; +@color-outer-description: #999999; +@color-outer-bg: #2b3e50; +@color-outer-header: @body-bg; +@color-outer-form-label: #666666; + +@color-breadcrumb-text-active: #9da3a7; +@color-breadcrumb-text: #9B9B9B; +@color-breadcrumb-background: #2b343d; + +@color-custom-input-icon: #666666; +@color-custom-input-border: #999999; + +@color-input-sidebar-control: #C4C4C4; + +@color-switch-input-bg: #f6f6f6; +@color-switch-input-on: #8da85e; +@color-switch-input-off: #cc3300; + +@color-custom-select-border: #b2b9be; +@color-custom-select-bg: #f6f6f6; +@color-custom-select-bg-hover: #4da7e8; + +@color-filelist-norecords-text: #666666; +@color-filelist-norecords-bg: #eeeeee; +@color-filelist-cb-border: #cccccc; +@color-filelist-title-hero: #2b3e50; +@color-filelist-hero-item-bg: #ffffff; +@color-filelist-hero-hover-bg: @highlight-hover-bg; +@color-filelist-hero-hover-text: @highlight-hover-text; +@color-filelist-hero-active-bg: @highlight-active-bg; +@color-filelist-hero-active-text: @highlight-active-text; + +@color-fancy-master-tabs-bg: @brand-secondary-darker; +@color-fancy-master-tabs-active-text: #ffffff; +@color-fancy-master-tabs-inactive-text: rgba(255, 255, 255, .35); +@color-fancy-master-panel-bg: @brand-secondary-darker; + +@color-fancy-secondary-tabs-bg: #475354; +@color-fancy-secondary-tabs-active-text: #ffffff; +@color-fancy-secondary-tabs-inactive-text: #919898; + +@color-fancy-primary-tabs-bg: #7F8C8D; +@color-fancy-primary-tabs-inactive-text: #95a5a6; +@color-fancy-primary-tabs-active-text: #808c8d; +@color-fancy-primary-tabs-active-bg: #fafafa; +@color-fancy-primary-tabs-inactive-bg: #d5d9d8; + +@color-fancy-form-tabless-fields-bg: @brand-secondary; +@color-fancy-form-label: rgba(255, 255, 255, .5); +@color-fancy-form-text: #ffffff; +@color-fancy-form-text-selection: @brand-secondary-darker; +@color-fancy-form-placeholder: rgba(255, 255, 255, .5); +@color-fancy-form-inactive-tab: #2c9cb9; + +@color-sortable-caret: #999999; +@color-sortable-active: @brand-secondary; + +@color-report-widget-title: #7e8c8d; +@color-report-widget-control-inactive: #b6b6b6; +@color-report-widget-description: @color-report-widget-title; +@color-report-widget-link: @color-report-widget-title; + +@color-treeview-item-bg: #ffffff; +@color-treeview-item-title: #2b3e50; +@color-treeview-item-comment: #95a5a6; +@color-treeview-control: #bdc3c7; +@color-treeview-hover-bg: @highlight-hover-bg; +@color-treeview-hover-text: @highlight-hover-text; +@color-treeview-active-bg: @highlight-active-bg; +@color-treeview-active-text: @highlight-active-text; +@color-treeview-item-active-comment: #8f8f8f; +@color-treeview-submenu-text: #ffffff; +@color-treeview-light-submenu-bg: #2581b8; +@color-treeview-light-submenu-border: #328ec8; + +// +// Sizes +// -------------------------------------------------- +@size-tiny: 50px; +@size-small: 100px; +@size-large: 200px; +@size-huge: 250px; +@size-giant: 350px; + +// +// Media breakpoints +// -------------------------------------------------- + +@menu-breakpoint-min: 770px; +@menu-breakpoint-max: (@menu-breakpoint-min - 1); diff --git a/modules/backend/assets/less/dashboard/dashboard.less b/modules/backend/assets/less/dashboard/dashboard.less new file mode 100644 index 0000000..8b30885 --- /dev/null +++ b/modules/backend/assets/less/dashboard/dashboard.less @@ -0,0 +1,17 @@ +@import "../../../../backend/assets/less/core/boot.less"; + +.dashboard-container > .report-container { + &.loading { + position: absolute; + width: 100%; + height: 100%; + + .loading-indicator-container { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + } + } +} diff --git a/modules/backend/assets/less/layout/fancylayout.less b/modules/backend/assets/less/layout/fancylayout.less new file mode 100644 index 0000000..21c8c02 --- /dev/null +++ b/modules/backend/assets/less/layout/fancylayout.less @@ -0,0 +1,733 @@ +// +// FANCY LAYOUT +// Applies branding colours to the Backend UI. +// + +// +// --- TABS +// + +// Master tabs +body.fancy-layout .master-tabs.control-tabs, +.master-tabs.control-tabs.fancy-layout { + overflow: hidden; + + &:before, &:after { + top: 13px; + font-size: 14px; + color: @color-fancy-master-tabs-inactive-text; + } + &:before { left: 8px; } + &:after { right: 8px; } + &.scroll-before:before { color: @color-fancy-master-tabs-active-text; } + &.scroll-after:after { color: @color-fancy-master-tabs-active-text; } + + > div > div.tabs-container { + background: @color-fancy-master-tabs-bg; + padding-left: 20px; + padding-right: 20px; + + > ul.nav-tabs { + margin-left: -8px; + > li { + margin-left: -5px; + top: 1px; + padding-top: 3px; + + span.tab-close { + top: 14px; + right: -3px; + left: auto; + z-index: 110; + font-family: sans-serif; + + i { + top: 4px; + right: 1px; + color: rgba(255, 255, 255, 0.3) !important; + font-style: normal; + font-weight: bold; + font-size: 16px; + + &:hover { color: @color-fancy-master-tabs-active-text !important; } + } + } + + a { + border-bottom: none; + background: transparent; + font-size: 14px; + color: @color-fancy-master-tabs-inactive-text; + padding: 6px 0 0 24px!important; + overflow: visible; + + > span.title { + position: relative; + display: inline-block; + padding: 12px 5px 0 5px; + height: 38px; + font-size: 14px; + z-index: 100; + background-color: @color-fancy-form-inactive-tab; + + &:before, &:after { + content: ' '; + position: absolute; + width: 20px; + display: block; + height: 37px; + top: 0; + z-index: 100; + background-color: @color-fancy-form-inactive-tab; + } + + &:before { + left: -14px; + .border-radius(8px 0 0 0); + .transform( ~'skewX(-20deg)'); + + } + + &:after { + right: -14px; + .border-radius(0 8px 0 0); + .transform( ~'skewX(20deg)'); + } + + span { + border-top: none; + padding: 0; + margin-top: 0; + overflow: visible; + } + } + + &:before { + z-index: 110; + position: absolute; + top: 18px; + left: 22px; + } + + &[class*=icon] > span.title { + padding-left: 18px; + } + } + + &.active { + a { + z-index: 107; + color: @color-fancy-master-tabs-active-text; + } + span.tab-close i { color: @color-fancy-master-tabs-active-text; } + + a > span.title { + background-color: @color-fancy-form-tabless-fields-bg; + z-index: 105; + &:before { + z-index: 107; + background-color: @color-fancy-form-tabless-fields-bg; + } + &:after { + background-color: @color-fancy-form-tabless-fields-bg; + z-index: 107; + } + } + } + + &[data-modified] { + span.tab-close i { + top: 5px; + .hide-text(); + + &:before { + .icon(@circle); + font-size: 9px; + } + } + } + + &:first-child { + margin-left: 0; + } + } + } + } + + &[data-closable] { + > div > div.tabs-container { + > ul.nav-tabs { + > li { + a > span.title { + padding-right: 10px; + } + } + } + } + } + + &.has-tabs { + &:before, &:after {display: block;} + } + + &.has-tabs { + > div.tab-content { + background: @body-bg; + } + } + + > .tab-content > .tab-pane { + padding: 0; + + &.padded-pane { + padding: @padding-standard @padding-standard 0 @padding-standard; + } + } +} + +// Primary Tabs +.fancy-layout *:not(.nested-form):not(.modal-body) > .form-widget > .layout-row > .control-tabs.primary-tabs, +*:not(.nested-form):not(.modal-body) > .form-widget > .layout-row > .control-tabs.fancy-layout.primary-tabs { + &.master-area { + > div > ul.nav-tabs { + .transition(background-color 0.5s); + background: @color-fancy-form-tabless-fields-bg; + } + } + + > div > ul.nav-tabs { + background: @color-fancy-primary-tabs-bg; + margin-left: 0!important; + margin-right: 0!important; + + &:before { + display: none; + } + + > li { + background: transparent; + border-right: none; + margin-right: -8px; + + &:first-child { + margin-left: -5px; + } + + a { + background: transparent; + border: none; + padding: 12px 16px 0px; + font-size: 14px; + font-weight: 400; + color: @color-fancy-primary-tabs-inactive-text; + + span.title { + background: @color-fancy-primary-tabs-inactive-bg; + border-top: none; + padding: 5px 5px 3px 5px; + + &:before, &:after { + background: @color-fancy-primary-tabs-inactive-bg; + border-width: 0; + top: 0; + } + + &:before { + left: -20px; + } + + &:after { + right: -20px; + } + + span { + border-width: 0; + vertical-align: top; + } + } + } + + &.active { + a { + color: @color-fancy-primary-tabs-active-text; + &:before { + display: none; + } + + span.title { + background: @color-fancy-primary-tabs-active-bg; + + &:before, &:after { + background: @color-fancy-primary-tabs-active-bg; + } + } + } + } + } + } + + > .tab-content > .tab-pane { + padding: @padding-standard @padding-standard 0 @padding-standard; + + &.pane-compact { + padding: 0; + } + } + + &.collapsed { + display: none; + } + + &.has-tabs { + > div.tab-content { + background: @body-bg; + } + } +} + +// Secondary tabs +.fancy-layout *:not(.nested-form):not(.modal-body) > .form-widget > .layout-row > .control-tabs.secondary-tabs { + // Target horizontal scroll indicators + &:before { + left: 5px; + } + &:after { + right: 5px; + } + > div > ul.nav-tabs { + background: @color-fancy-secondary-tabs-bg; + > li { + border-right: none; + padding-right: 0; + margin-right: 0; + a { + background: transparent; + border: none; + padding: 12px 10px 13px 10px; + font-size: 14px; + font-weight: normal; + line-height: 14px; + color: @color-fancy-secondary-tabs-inactive-text; + + span { + span { + overflow: visible; + border-top: none; + margin-top: 0; + padding-top: 0; + } + } + } + + &:first-child { + padding-left: 15px; // Will cause issues when first child is hidden + } + + &.active { + a {color: @color-fancy-secondary-tabs-active-text;} + } + } + } + + .tab-collapse-icon { + position: absolute; + display: block; + text-decoration: none; + outline: none; + .opacity(0.6); + .transition(all 0.3s); + font-size: 12px; + color: @color-fancy-master-tabs-active-text; + right: 11px; + + &:hover { + text-decoration: none; + .opacity(1); + } + + &.primary { + color: @color-fancy-master-tabs-active-text; + top: 12px; + right: 11px; + bottom: auto; + z-index: 100; + .scaleAxes(1, -1); + + i { + position: relative; + display: block; + } + } + } + + &.primary-collapsed { + .tab-collapse-icon.primary { + .scaleAxes(1, 1); + } + } + + &.secondary-content-tabs { + > div > ul.nav-tabs { + background: @body-bg; + + > li { + margin-left: -19px; + + &:first-child { + margin-left: 0; + padding-left: 8px; + } + + a { + padding: 8px 16px 0 16px; + font-weight: 400; + height: 36px; + color: #2b3e50; + .opacity(0.6); + + > span.title { + position: relative; + display: inline-block; + padding: 8px 5px 9px 5px; + font-size: 14px; + z-index: 100; + height: 27px!important; + background-color: transparent; + + &:before, &:after { + content: ' '; + position: absolute; + background-color: white; + width: 15px; + height: 28px; + top: 0; + z-index: 100; + display: none; + } + + &:before { + left: -11px; + .border-radius(8px 0 0 0); + .transform( ~'skewX(-20deg)'); + } + + &:after { + right: -11px; + .border-radius(0 8px 0 0); + .transform( ~'skewX(20deg)'); + } + + span { + height: 18px; + font-size: 14px; + } + } + } + + &.active a { + .opacity(1); + + > span.title { + background-color: white; + &:before, &:after { + display: block; + } + } + } + } + } + + .tab-collapse-icon.primary { + color: #000000; + } + + &.primary-collapsed { + .tab-collapse-icon.primary { + color: @color-fancy-master-tabs-active-text; + } + + > div > ul.nav-tabs { + background: @color-fancy-form-tabless-fields-bg; + + > li { + a { + color: white; + + > span.title { + &:before, &:after { + background-color: white; + } + } + } + + &.active a { + color: #2b3e50; + } + } + } + } + } + + &.has-tabs { + > div.tab-content { + background: @body-bg; + } + } + + > .tab-content > .tab-pane { + padding: 0; + + &.padded-pane { + padding: @padding-standard @padding-standard 0 @padding-standard; + } + } +} + +// Tabless (outside) fields +.fancy-layout *:not(.nested-form):not(.modal-body) > .form-widget > .layout-row > .form-tabless-fields { + .clearfix(); + position: relative; + background: @color-fancy-form-tabless-fields-bg; + padding: 18px 23px 0 23px; + .transition(all 0.5s); + + label { + text-transform: uppercase; + color: @color-fancy-form-label; + margin-bottom: 0; + } + + .form-control[disabled] { + background-color: rgba(29, 29, 29, 0.11) !important; + } + + input[type=text] { + background: transparent; + border: none; + color: @color-fancy-form-text; + font-size: 35px; + font-weight: 100; + height: auto; + padding: 0; + .placeholder(@color-fancy-form-placeholder); + .box-shadow(none); + + &:focus, &:hover { + background-color: rgba(255, 255, 255, 0.1); + } + } + + .form-group { + padding-bottom: 0; + + &.is-required { + > label:after { + display: none; + } + } + } + + .tab-collapse-icon { + position: absolute; + display: block; + text-decoration: none; + outline: none; + .opacity(0.6); + .transition(all 0.3s); + font-size: 12px; + color: @color-fancy-master-tabs-active-text; + right: 11px; + + &:hover { + text-decoration: none; + .opacity(1); + } + + &.primary { + color: @color-fancy-master-tabs-active-text; + top: 12px; + right: 11px; + bottom: auto; + z-index: 100; + .scaleAxes(1, -1); + + i { + position: relative; + display: block; + } + } + + &.tabless { + top: 14px; + } + } + + &.collapsed { + padding: 5px 23px 0 10px; + + .tab-collapse-icon { + &.tabless { + .scaleAxes(1, -1); + } + } + + .form-group:not(.collapse-visible) { + display: none; + } + + .form-buttons { + margin-left: 10px; + padding-bottom: 0; + } + } + + .loading-indicator-container { + .loading-indicator { + background-color: @color-fancy-form-tabless-fields-bg; + padding: 0 0 0 30px; + color: @color-fancy-form-label; + margin-top: 1px; + height: 90%; + font-size: 12px; + line-height: 100%; + > span { + left: -10px; + top: 18px; + } + } + } +} + +// +// --- FANCY BREADCRUMBS +// + +body.breadcrumb-fancy .control-breadcrumb, +.control-breadcrumb.breadcrumb-fancy { + margin-bottom: 0; + + background-color: mix(black, saturate(@color-fancy-form-tabless-fields-bg, 20%), 16%); + + li { + background-color: mix(black, saturate(@color-fancy-form-tabless-fields-bg, 20%), 31%); + color: rgba(255,255,255, .5); + + a { + opacity: .5; + .transition(all 0.3s ease); + &:hover { + opacity: 1; + + } + } + + &:not(:last-child)::before { + border-left-color: @color-fancy-form-tabless-fields-bg; + opacity: .5; + } + + &:after { + border-left-color: mix(black, saturate(@color-fancy-form-tabless-fields-bg, 20%), 31%); + } + + &:last-child { + background-color: mix(black, saturate(@color-fancy-form-tabless-fields-bg, 20%), 16%); + + &:before { + opacity: 1; + border-left-color: mix(black, saturate(@color-fancy-form-tabless-fields-bg, 20%), 16%); + } + } + } +} + +// +// --- FORM BUTTONS +// + +.fancy-layout *:not(.nested-form):not(.modal-body) > .form-widget > .layout-row > .control-tabs .form-buttons:not(.normalized), +.fancy-layout *:not(.nested-form):not(.modal-body) > .form-widget > .layout-row > .form-tabless-fields .form-buttons:not(.normalized) { + .transition(all 0.5s); + padding-top: 14px; + padding-bottom: 5px; + + .btn { + padding: 0; + margin-right: 5px; + margin-top: -6px; + margin-right: 30px; + background: transparent; + color: @color-fancy-master-tabs-active-text; + font-weight: normal; + .box-shadow(none); + + .opacity(0.5); + .transition(all 0.3s ease); + + &:hover { + .opacity(1); + } + + &:last-child { + margin-right: 0; + } + + &[class^="wn-icon-"], + &[class*=" wn-icon-"], + &[class^="oc-icon-"], + &[class*=" oc-icon-"] { + &:before { + opacity: 1; + } + } + } +} + +.fancy-layout form[class$="-data-changed"] *:not(.nested-form):not(.modal-body) > .form-widget > .layout-row > .control-tabs .btn.save { + .opacity(1); +} + +// +// --- FIELDS AND WIDGETS +// + +// Code editor +.fancy-layout *:not(.nested-form):not(.modal-body) > .form-widget > .layout-row > .control-tabs > .tab-content > .tab-pane > .form-group > .field-codeeditor { + border: none !important; + .border-radius(0); + + .editor-code { + .border-radius(0); + } +} + +// Rich editor +.fancy-layout *:not(.nested-form):not(.modal-body) > .form-widget > .layout-row > .control-tabs > .tab-content > .tab-pane > .form-group > .field-richeditor { + border: none; + border-left: 1px solid @color-form-field-border !important; + + &, .fr-toolbar, .fr-wrapper { + .border-radius(0); + .border-top-radius(0); + } +} + +// Rich editor in a secondary content tab +.fancy-layout *:not(.nested-form):not(.modal-body) > .form-widget > .layout-row > .control-tabs.secondary-content-tabs > .tab-content > .tab-pane > .form-group > .field-richeditor { + .fr-toolbar { + background: white; + } +} + +// Rich editor when the side panel is not fixed +body.side-panel-not-fixed .fancy-layout *:not(.nested-form):not(.modal-body) > .form-widget > .layout-row > .control-tabs > .tab-content > .tab-pane > .form-group > .field-richeditor, +body.side-panel-not-fixed.fancy-layout *:not(.nested-form):not(.modal-body) > .form-widget > .layout-row > .control-tabs > .tab-content > .tab-pane > .form-group > .field-richeditor { + border-left: none; +} + +// Loading indicator +html.cssanimations .fancy-layout *:not(.nested-form):not(.modal-body) > .form-widget > .layout-row > .form-tabless-fields .loading-indicator-container .loading-indicator > span { + .animation(spin 1s linear infinite); + background-image: url('../../../system/assets/ui/images/loader-white.svg'); + background-size: 20px 20px; +} diff --git a/modules/backend/assets/less/layout/flexlayout.less b/modules/backend/assets/less/layout/flexlayout.less new file mode 100644 index 0000000..fe00e05 --- /dev/null +++ b/modules/backend/assets/less/layout/flexlayout.less @@ -0,0 +1,50 @@ +.flex-layout-column { + .flex-display(); + .flex-direction-column(); + + &.full-height-strict { + height: 100%; + } + + &.absolute { + position: absolute!important; + } + + &.fill-container { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + } +} + +.flex-layout-row { + .flex-display(); + .flex-direction-row(); +} + +.flex-layout-column, .flex-layout-row { + &.justify-center {.justify-content(center);} + &.align-center { + .align-items(center); + .align-content(center); + } + + &.full-height { + min-height: 100%; + // height: 100%; + } +} + +.flex-layout-item { + margin: 0; + &.fix { .flex-fix(); } + &.stretch { .flex-stretch(); } + &.stretch-constrain { .flex-stretch-constrain(); } + &.center { .align-self(center); } + + &.relative { position: relative; } + + &.layout-container { max-width: none; } +} diff --git a/modules/backend/assets/less/layout/flyout.less b/modules/backend/assets/less/layout/flyout.less new file mode 100644 index 0000000..a276396 --- /dev/null +++ b/modules/backend/assets/less/layout/flyout.less @@ -0,0 +1,48 @@ +.flyout-container { + > .flyout { + overflow: hidden; + width: 0; + left: 0!important; + .transition(width 0.1s); + } +} + +.flyout-overlay { + width: 100%; + height: 100%; + top: 0; + z-index: 5000; + position: absolute; + background-color: rgba(0,0,0,0); + .transition(background-color 0.3s); +} + +.flyout-toggle { + position: absolute; + top: 20px; + left: 0; + width: 23px; + height: 25px; + background: #2b3e50; + cursor: pointer; + .border-right-radius(4px); + color: #bdc3c7; + font-size: 10px; + + i { + margin: 7px 0 0 6px; + display: inline-block; + } + + &:hover i { + color: #ffffff; + } +} + +body.flyout-visible { + overflow: hidden; + + .flyout-overlay { + background-color: rgba(0,0,0,0.3); + } +} \ No newline at end of file diff --git a/modules/backend/assets/less/layout/footer.less b/modules/backend/assets/less/layout/footer.less new file mode 100644 index 0000000..f3ae25f --- /dev/null +++ b/modules/backend/assets/less/layout/footer.less @@ -0,0 +1,32 @@ +@footer-zindex: 100; +@footer-height: 60; + +#layout-footer { + width: 100%; + z-index: @footer-zindex; + height: @footer-height + 0px; + position: fixed; + bottom: 0; + color: @color-footer-text; + background-color: @color-footer; + border-top: 1px solid @color-footer-border; + + .brand, .tagline { + margin: 10px; + height: (@footer-height - 20) + 0px; + line-height: (@footer-height - 20) + 0px; + } + + .brand { + float: left; + font-size: 16px; + .logo { margin: 0 10px; } + .name { } + } + + .tagline { + float: right; + p { color: lighten(@color-footer-text, 20%); } + } +} + diff --git a/modules/backend/assets/less/layout/layout.less b/modules/backend/assets/less/layout/layout.less new file mode 100644 index 0000000..7dc5739 --- /dev/null +++ b/modules/backend/assets/less/layout/layout.less @@ -0,0 +1,234 @@ +// +// Common layout elements +// -------------------------------------------------- + +html:not(.mobile) body.drag * { + cursor: grab !important; + cursor: -webkit-grab !important; + cursor: -moz-grab !important; +} + +// Used by sortable plugin +body.dragging, body.dragging * { + cursor: move !important; +} + +body.loading, body.loading * { + cursor: wait !important; +} + +body.no-select { + .user-select(none); + cursor: default !important; +} + +// +// Layout canvas +// + +html, +body { + height: 100%; + /* The html and body elements cannot have any padding or margin. */ +} + +body { + font-family: @font-family-base; + background: @body-bg; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +#layout-canvas { + min-height: 100%; + height: 100%; +} + +// +// Font +// + +// Removed for performance reasons +// +// @import url(https://fonts.googleapis.com/css?family=Noto+Sans:400,400italic,700,700italic); +// +// body { +// font-family: 'Noto Sans', sans-serif; +// } + +// +// Tabs override for Layout +// Primary tabs should use inset by default, unless otherwise specified +// -------------------------------------------------- + +.control-tabs.primary-tabs { + > ul.nav-tabs, > div > ul.nav-tabs, > div > div > ul.nav-tabs { + margin-left: -(@padding-standard); + margin-right: -(@padding-standard); + } + + &.tabs-no-inset { + > ul.nav-tabs, > div > ul.nav-tabs, > div > div > ul.nav-tabs { + margin-left: 0; + margin-right: 0; + } + } +} + +// +// Flexible layout system +// -------------------------------------------------- + +.layout { + .layout-cell() { + display: table-cell; + vertical-align: top; + height: 100%; + + &.layout-container, .layout-container, &.padded-container, .padded-container { + padding: @padding-standard @padding-standard 0 @padding-standard; + + // Container to sit flush to the element above + .container-flush { + padding-top: 0; + } + } + + .layout-relative { + position: relative; + height: 100%; + } + + .layout-absolute { + position: absolute; + height: 100%; + width: 100%; + } + + &.min-size { + width: 0; + } + + &.min-height { + height: 0; + } + + &.center { + text-align: center; + } + + &.middle { + vertical-align: middle; + } + } + + display: table; + table-layout: fixed; + height: 100%; + width: 100%; + + > .layout-row { + display: table-row; + vertical-align: top; + height: 100%; + + > .layout-cell { + .layout-cell(); + } + + &.min-size { + height: 0.1px; + } + } + + > .layout-cell { + .layout-cell(); + } +} + +.whiteboard { + background: white; +} + +.layout-fill-container { + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; +} + +// +// Calculated fixed width +// + +[data-calculate-width] { + > form, > div { + display: inline-block; + } +} + +// +// Layout styles +// + +body.compact-container { + .layout { + &.layout-container, .layout-container { padding: 0 !important; } + } +} + +body.slim-container { + .layout { + &.layout-container, .layout-container { padding-left: 0 !important; padding-right: 0 !important; } + } +} + +// +// Screen specific +// + +@media (max-width: @screen-sm) { + .layout { + .hide-on-small { + display: none; + } + + // + // Layout with a responsive sidebar + // + + &.responsive-sidebar { + > .layout-cell:first-child { + display: table-footer-group; + height: auto; + + .control-breadcrumb { + display: none; + } + } + + > .layout-cell:last-child { + display: table-header-group; + width: auto; + height: auto; + + .layout-absolute { + position: static; + } + } + } + } +} + +// +// Browser specific +// + +// Remove focus outline for mouse clicks, keep for keyboard navigation +@supports (-moz-appearance: none) { + a:focus:not(:focus-visible) { + outline: none; + } +} + diff --git a/modules/backend/assets/less/layout/mainmenu.less b/modules/backend/assets/less/layout/mainmenu.less new file mode 100644 index 0000000..f4b8c37 --- /dev/null +++ b/modules/backend/assets/less/layout/mainmenu.less @@ -0,0 +1,680 @@ +// +// Top navigation bar +// -------------------------------------------------- + +@mainmenu-mode-tile-height: 78px; +@mainmenu-mode-inline-height: 60px; +@mainmenu-mode-collapse-height: 45px; + +@mainmenu-icon-dimension: 30px; +@mainmenu-tile-dimension: 65px; +@mainmenu-tile-label-height: 20px; +@mainmenu-tile-label-width: 100px; + +body.mainmenu-open { + overflow: hidden; + position: fixed; +} + +.mainmenu-item-link() { + display: inline-block; + font-size: @font-size-base; + color: inherit; + + &:hover { + background-color: transparent; + } + + &:active, &:focus { + text-decoration: none; + color: @color-mainmenu-inactive; + } + + i { + line-height: 1; + font-size: 30px; + vertical-align: middle; + } +} + +.mainmenu-item-link-active() { + // background: @color-mainmenu-active-bg; + // .border-radius(3px); + // .box-shadow(inset 0 -2px 0 rgba(0,0,0,.25)); +} + +.mainmenu-set-height(@height) { + height: @height; + + ul.mainmenu-toolbar { + li.mainmenu-quick-action { + a { + height: @height; + line-height: @height; + } + } + + li.mainmenu-account { + > a { + height: @height; + line-height: @height; + } + } + } + + ul li .mainmenu-accountmenu { + top: @height + 10; + } +} + +.mainmenu-tooltip { + .tooltip-inner { + font-size: @font-size-base - 1; + padding: 6px 16px; + } +} + +ul.mainmenu-nav { + font-size: @font-size-base; + + li { + /* Fix for SVG icons not rendering on initial page load until repaint (hover, move, etc) */ + .svg-icon { + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + } + + span.counter { + display: block; + position: absolute; + top: .143em; + right: 0; + padding: .143em .429em .214em .286em; + background-color: @color-sidebarnav-counter-bg; + color: @color-sidebarnav-counter-text; + font-size: .786em; + line-height: 100%; + .border-radius(3px); + .opacity(1); + .scale(1); + .transition(all 0.3s); + + &.empty { + .opacity(0); + .scale(0); + } + } + } +} + +nav#layout-mainmenu { + background-color: @color-mainmenu; + padding: 0 0 0 20px; + line-height: 0; + white-space: nowrap; + display: flex; + + a { + text-decoration: none; + &:focus { + background: transparent; + } + } + + ul { + margin: 0; + padding: 0; + list-style: none; + float: left; + white-space: nowrap; + overflow: hidden; + + li { + color: @color-mainmenu-inactive; + display: inline-block; + vertical-align: top; + position: relative; + margin-right: 30px; + + a { + .mainmenu-item-link(); + padding: 14px 0 10px; + + img.svg-icon { + height: 30px; + width: 30px; + margin-right: 10px; + position: relative; + top: 0; + } + } + } + + &.nav { + display: inline-block; + } + } + + .toolbar-item { + flex: 1 1 auto; + display: block; + padding-right: 0; + overflow: hidden; + + &-account { + flex: 0 0 auto; + } + + &:before, &:after { + margin-top: 0; + } + + &:before { + left: -12px; + } + + &:after { + right: -12px; + } + + &.scroll-active-before:before { + color: @color-mainmenu-active; + } + + &.scroll-active-after:after { + color: @color-mainmenu-active; + } + } + + // + // Toolbar + // + + ul.mainmenu-toolbar { + li.mainmenu-quick-action { + margin: 0; + + &:first-child { + margin-left: 21px; + } + + i { + font-size: 20px; + } + + a { + position: relative; + padding: 0 10px; + top: -1px; + } + } + + li.mainmenu-account { + margin-right: 0; + + > a { + padding: 0 15px 0 10px; + font-size: @font-size-base - 1; + position: relative; + } + + &.highlight > a { + z-index: @zindex-popover; + } + + img.account-avatar { + width: 45px; + height: 45px; + } + + .account-name { + //font-weight: bold; + margin-right: 15px; + } + + ul { + line-height: 23px; + } + } + } + + // + // Fading animation (disabled) + // + + &:hover { + ul.mainmenu-nav li { + //.transition(opacity .15s ease); + //.opacity(1); + } + } + + ul.mainmenu-nav li { + //.opacity(.65); + //.transition(opacity 5s ease); + //.transition-delay(5s); + + &.active { + //.opacity(1); + } + } +} + +// +// SVG support +// + +html.svg { + nav#layout-mainmenu, + .mainmenu-collapsed { + img.svg-icon { + display: inline-block; + } + } +} + +// +// User account menu +// + +nav#layout-mainmenu ul li .mainmenu-accountmenu { + position: fixed; + top: 0; // See mode for this value + right: @padding-standard; + background: @color-accountmenu-bg; + z-index: @zindex-popover; + display: none; + .box-shadow(@overlay-box-shadow); + border-radius: @border-radius-base; + + &.active { + display: block; + } + + &:after { + .triangle(up, 17px, 7px, @color-accountmenu-bg); + right: 9px; + top: -7px; + position: absolute; + } + + ul { + float: none; + display: block; + overflow: visible; + } + + li { + padding: 0; + margin: 0; + font-weight: normal; + text-align: left; + display: block; + + a { + display: block; + padding: (@padding-standard * 0.5) (@padding-standard * 1.5); + text-align: left; + font-size: @font-size-base; + color: @color-accountmenu-text; + + &:hover, &:focus { + background: @highlight-hover-bg; + color: @highlight-hover-text; + } + + &:active { + background: @highlight-active-bg; + color: @highlight-active-text; + } + } + + &:first-child a { + &:hover, &:focus, &:active { + &:after { + .triangle(up, 17px, 7px, @highlight-hover-bg); + position: absolute; + right: 9px; + top: -7px; + z-index: 102; + } + } + &:active { + &:after { + .triangle(up, 17px, 7px, @highlight-active-bg); + } + } + } + } + + li.divider { + height: 1px; + width: 100%; + background-color: @color-accountmenu-divider; + } +} + +// +// Navbar (Inline mode) +// + +nav#layout-mainmenu.navbar-mode-inline, +nav#layout-mainmenu.navbar-mode-inline_no_icons { + .mainmenu-set-height(@mainmenu-mode-inline-height); + + ul.mainmenu-nav { + li { + margin: 5px 0; + + a { + padding: 10px 15px; + + .nav-icon { + position: relative; + top: -1px; + margin-right: 5px; + width: @mainmenu-icon-dimension; + height: @mainmenu-icon-dimension; + i, img { margin: 0; } + } + .nav-label { + line-height: @mainmenu-icon-dimension; + } + } + + &:first-child { + margin-left: -13px; + } + + &:last-child { + margin-right: 0; + } + } + + li.active { + .mainmenu-item-link-active(); + + // &:first-child { + // margin-left: 0; + // } + } + + } +} + +// +// Navbar (Inline no icons mode) +// +nav#layout-mainmenu.navbar-mode-inline_no_icons .nav-icon { + display: none !important; +} + +// +// Navbar (Tiles mode) +// + +nav#layout-mainmenu.navbar-mode-tile { + .mainmenu-set-height(@mainmenu-mode-tile-height); + .mainmenu-navbar-tiles(); +} + +.mainmenu-navbar-tiles() { + ul.mainmenu-nav { + li a { + position: relative; + width: @mainmenu-tile-dimension; + height: @mainmenu-tile-dimension; + + // Offset from bottom + @tile-bottom-offset: 4; + + .nav-icon { + text-align: center; + display: block; + position: absolute; + top: 50%; + left: 50%; + margin-left: -(@mainmenu-icon-dimension / 2); + margin-top: -((@mainmenu-tile-dimension - @mainmenu-tile-label-height) / 2) - @tile-bottom-offset; + width: @mainmenu-icon-dimension; + height: @mainmenu-icon-dimension; + i, img { margin: 0; } + } + + .nav-label { + display: block; + width: @mainmenu-tile-label-width; + height: @mainmenu-tile-label-height; + line-height: @mainmenu-tile-label-height; + position: absolute; + bottom: @tile-bottom-offset + 0px; + left: 50%; + padding: 0 5px; + margin-left: -(@mainmenu-tile-label-width / 2); + overflow: hidden; + text-overflow: ellipsis; + text-align: center; + } + } + + li { + padding: 0 15px; + margin: 7px 0 0; + + &:first-child { + margin-left: -7px; + } + + &:hover { + .nav-label { + width: auto; + min-width: @mainmenu-tile-label-width; + text-overflow: all; + overflow: visible; + z-index: 2; + } + } + + } + + li.active { + .mainmenu-item-link-active(); + + a { + // font-weight: bold; + } + + &:first-child { + margin-left: 0; + } + } + } +} + +// +// Mobile (Collapsed mode) +// + +nav#layout-mainmenu { + .menu-toggle { + height: @mainmenu-mode-collapse-height; + line-height: @mainmenu-mode-collapse-height; + font-size: @font-size-base + 2; + display: none; + + .menu-toggle-icon { + background: #333; + display: inline-block; + height: @mainmenu-mode-collapse-height; + line-height: @mainmenu-mode-collapse-height; + width: @mainmenu-mode-collapse-height; + text-align: center; + opacity: .7; + + i { + line-height: @mainmenu-mode-collapse-height; + font-size: 20px; + vertical-align: bottom; + } + } + + .menu-toggle-title { + margin-left: 10px; + } + + &:hover { + .menu-toggle-icon { + opacity: 1; + } + } + } +} + +body.mainmenu-open { + nav#layout-mainmenu { + .menu-toggle-icon { + opacity: 1; + } + } +} + +nav#layout-mainmenu.navbar-mode-collapse { + .mainmenu-navbar-collapse(); +} + +@media (max-width: @menu-breakpoint-max) { + nav#layout-mainmenu.navbar { + .mainmenu-navbar-collapse(); + } +} + +.mainmenu-navbar-collapse() { + padding-left: 0; + + .mainmenu-set-height(@mainmenu-mode-collapse-height); + + ul.mainmenu-toolbar li.mainmenu-account > a { + padding-right: 0; + } + + ul li .mainmenu-accountmenu:after { + right: 13px; + } + + ul.nav { display: none; } + + .menu-toggle { + display: inline-block; + color: @color-mainmenu-active !important; + // font-weight: bold; + } +} + +.mainmenu-collapsed { + position: absolute; + height: 100%; + top: 0; + left: 0; + margin: 0; + background: @color-mainmenu-collapsed; + + > div { + display: block; + height: 100%; + + .mainmenu-navbar-tiles(); + + ul.mainmenu-nav li:first-child { + margin-left: 0; + } + + ul { + margin: 0; + padding: 5px 0 15px 15px; + overflow: hidden; + } + + ul li { + color: @color-mainmenu-inactive; + display: inline-block; + vertical-align: top; + position: relative; + margin-right: 30px; + } + + ul li a { + .mainmenu-item-link(); + + img.svg-icon { + height: 30px; + width: 30px; + position: relative; + top: 0; + } + } + } + + .vertical-scroll-marker(@color-mainmenu-inactive); +} + +body.mainmenu-open .mainmenu-collapsed ul { + position: absolute; + left: 0; + top: 10px; + bottom: 10px; +} + +html.mobile { + .mainmenu-collapsed ul { + overflow: auto; + -webkit-overflow-scrolling: touch; + } +} + +// +// Misc +// + +nav#layout-mainmenu.navbar ul li:hover, +.mainmenu-collapsed li:hover { + a { + &:active, &:focus { + color: @color-mainmenu-active !important; + } + } +} + +.touch .mainmenu-collapsed li a:hover { + color: @color-mainmenu-inactive; +} + +nav#layout-mainmenu.navbar ul li, +.mainmenu-collapsed li { + + // Used by account menu + &.highlight > a { + color: @color-mainmenu-active !important; + } + + &.active { + color: @color-mainmenu-active !important; + + a { + color: @color-mainmenu-active !important; + } + } + + &:hover { + color: @color-mainmenu-active; + background: transparent; + } +} + +body.drag { + nav#layout-mainmenu.navbar ul.nav li, + .mainmenu-collapsed ul li { + &:hover { + color: @color-mainmenu-inactive; + } + } +} diff --git a/modules/backend/assets/less/layout/outerlayout.less b/modules/backend/assets/less/layout/outerlayout.less new file mode 100644 index 0000000..34aa513 --- /dev/null +++ b/modules/backend/assets/less/layout/outerlayout.less @@ -0,0 +1,147 @@ + +// Layout for "Outside" pages, such as the Login screen +// + +body.outer { + background: @color-outer-bg; + + .layout { + > .layout-row { + &.layout-head { + text-align: center; + background: @color-outer-header; + + > .layout-cell { + height: 40%; + padding: 50px 0; + .box-sizing(border-box); + vertical-align: middle; + position: relative; + + &:after { + .triangle(down, 56px, 20px, @color-outer-header); + position: absolute; + bottom: -20px; + left: 50%; + margin-left: -28px; + } + + h1.wn-logo, + h1.oc-logo { + .hide-text(); + display: inline-block; + width: 100%; + max-width: 450px; + height: 170px; + min-height: 72px; + } + } + } + + > .layout-cell { + vertical-align: top; + + .outer-form-container { + margin: 0 auto; + width: 436px; + padding: (@padding-standard * 2) 0; + + h2 { + font-size: 18px; + margin: 20px 0; + color: @color-outer-heading; + } + + .horizontal-form { + font-size: 0; + .flex-display(); + + input { + vertical-align: top; + margin-right: 9px; + display: inline-block; + border: none; + .border-radius(2px); + } + + button { + background: @link-color; + text-align: center; + font-size: 13px; + font-weight: 600; + height: 40px; + vertical-align: top; + .box-sizing(border-box); + } + } + + .remember { + label { + color: @color-outer-muted-text; + } + input#remember { + display: none; + } + } + + .forgot-password { + margin-top: 30px; + font-size: 13px; + top: 8px; + + a { + color: @color-outer-muted-text; + } + + &:before { + color: @color-outer-muted-text; + font-size: 14px; + position: relative; + margin-right: 5px; + } + } + } + } + } + } +} + +html.csstransitions { + body.outer { + .outer-form-container { + .transition(all 0.5s ease-out); + .scaleAxes(1, 1); + } + + &.preload { + .outer-form-container { + .scaleAxes(0.2, 0.2); + } + } + } +} + +@media (max-width: @screen-sm) { + body.outer .layout > .layout-row { + &.layout-head { + > .layout-cell { + padding: 50px @padding-standard; + } + } + + > .layout-cell .outer-form-container { + width: auto; + padding: @padding-standard * 2; + + .horizontal-form { + display: block; + + input { + display: block; + width: 100% !important; + margin-bottom: @padding-standard; + } + } + } + } +} diff --git a/modules/backend/assets/less/layout/sidenav.less b/modules/backend/assets/less/layout/sidenav.less new file mode 100644 index 0000000..259bc4f --- /dev/null +++ b/modules/backend/assets/less/layout/sidenav.less @@ -0,0 +1,116 @@ +// +// Side navigation bar +// -------------------------------------------------- + +.layout-sidenav-container { + width: 120px; +} + +#layout-sidenav { + position: absolute; + height: 100%; + width: 100%; + .box-sizing(border-box); + font-size: @font-size-base; + + ul { + position: relative; + margin: 0; + padding: 0; + height: 100%; + overflow: hidden; + + li { + display: block; + text-align: center; + position: relative; + + a { + padding: 1.429em .714em; + display: block; + font-size: .929em; + color: @color-sidebarnav-inactive-text; + font-weight: normal; + position: relative; + + &:hover { + text-decoration: none; + background-color: transparent; + } + + &:focus { + background: transparent; + } + + i { + color: @color-sidebarnav-inactive-icon; + display: block; + margin-bottom: 5px; + font-size: 2em; + } + } + + &:first-child a { + padding-top: 2.143em; + } + + &.active a, a:hover { + color: @color-sidebarnav-active-text; + i { color: @color-sidebarnav-active-icon; } + } + + span.counter { + display: block; + position: absolute; + top: 1.071em; + right: 1.071em; + padding: .143em .429em .214em .286em; + background-color: @color-sidebarnav-counter-bg; + color: @color-sidebarnav-counter-text; + font-size: .786em; + line-height: 100%; + .border-radius(3px); + .opacity(1); + .scale(1); + .transition(all 0.3s); + + &.empty { + .opacity(0); + .scale(0); + } + } + } + } +} + +@media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) { + #layout-sidenav { + font-size: 12px; + } + .layout-sidenav-container { + width: 100px; + } +} + +@media (max-width: @screen-xs-max) { + #layout-sidenav { + font-size: 10px; + } + .layout-sidenav-container { + width: 80px; + } +} + +html.mobile { + #layout-sidenav ul { + overflow: auto; + -webkit-overflow-scrolling: touch; + } +} + +#layout-sidenav.layout-sidenav ul.drag li:not(.active) a:hover, +.touch #layout-sidenav.layout-sidenav li:not(.active) a:hover { + color: @color-sidebarnav-inactive-text !important; + i { color: @color-sidebarnav-inactive-icon !important; } + &:after { display: none !important; } +} diff --git a/modules/backend/assets/less/layout/sidepanel.less b/modules/backend/assets/less/layout/sidepanel.less new file mode 100644 index 0000000..3771e83 --- /dev/null +++ b/modules/backend/assets/less/layout/sidepanel.less @@ -0,0 +1,97 @@ +// +// Side panel +// -------------------------------------------------- + +#layout-side-panel { + .fix-button { + position: absolute; + right: -25px; + top: 0; + display: none; + width: 25px; + height: 25px; + font-size: 13px; + background: #ecf0f1; + z-index: 120; + .opacity(0.5); + .border-radius(~'0 4px 4px 0'); + + i { + display: block; + text-align: center; + margin-top: 5px; + color: @color-scrollpanel-fix-button; + } + + &:hover { + text-decoration: none; + display: block; + .opacity(1)!important; + } + } + + &:hover { + .fix-button { + display: block; + } + } + + .fix-button-content-header .fix-button { + top: 46px; + } + + .sidepanel-content-header { + background: @brand-secondary-darker; + color: white; + font-size: 15px; + padding: 12px 20px 13px; + position: relative; + + &:after { + .triangle(down, 15px, 8px, @brand-secondary-darker); + position: absolute; + left: 14px; + bottom: -8px; + } + } +} + +body.side-panel-not-fixed { + #layout-side-panel { + display: none; + + .fix-button { + .opacity(0.5); + } + } +} + +body.display-side-panel { + #layout-side-panel { + display: block; + position: absolute; + // This needs to be higher than the dropdown overlay, otherwise the + // mouseout event fires and sidebar hides when opening a dropdown. + z-index: @zindex-dropdown; + width: 350px; + .box-shadow(3px 0px 3px 0 rgba(0, 0, 0, 0.1)); + } +} + +@media (min-width: @screen-md-min) { + body.side-panel-fix-shadow { + #layout-side-panel { + .box-shadow(none); + } + } +} + +.touch #layout-side-panel .fix-button { + display: none; +} + +@media (max-width: @screen-sm) { + #layout-side-panel .fix-button { + display: none; + } +} diff --git a/modules/backend/assets/less/winter.less b/modules/backend/assets/less/winter.less new file mode 100644 index 0000000..8c4bb2e --- /dev/null +++ b/modules/backend/assets/less/winter.less @@ -0,0 +1,56 @@ +// Vendor +@import "../vendor/sweet-alert/sweet-alert.less"; +@import "../vendor/jcrop/css/jquery.Jcrop.min.css"; +@import "../../../system/assets/vendor/prettify/prettify.css"; +@import "../../../system/assets/vendor/prettify/theme-desert.css"; + +// +// Winter Controls +// + +@import "core/boot.less"; +@import "controls/alert.less"; +@import "controls/global-notice.less"; +@import "controls/simplelist.less"; +@import "controls/scrollbar.less"; +@import "controls/filelist.less"; +@import "controls/common.less"; +@import "controls/reportwidgets.less"; +@import "controls/treelist.less"; +@import "controls/treeview.less"; +@import "controls/sidenav-tree.less"; +@import "controls/panels.less"; +@import "controls/selector-group.less"; +@import "controls/tree-path.less"; +@import "controls/namevaluelist.less"; +@import "controls/scrollpad.less"; +@import "controls/svg-icons.less"; +@import "controls/record-navigation.less"; + +// +// Winter Storm UI +// + +@import "../../../system/assets/ui/less/global.less"; + +// +// Combines layout and vendor styles +// + +// Core (shared elements) +@import "core/animations.less"; + +// Boot variables and mixins +@import "core/variables.less"; +@import "core/mixins.less"; + +// Layout +@import "layout/layout.less"; +@import "layout/flexlayout.less"; +@import "layout/mainmenu.less"; +@import "layout/sidenav.less"; +@import "layout/sidepanel.less"; +@import "layout/footer.less"; +@import "layout/outerlayout.less"; +@import "layout/fancylayout.less"; +@import "layout/flyout.less"; diff --git a/modules/backend/assets/ui/js/ajax/Handler.js b/modules/backend/assets/ui/js/ajax/Handler.js new file mode 100644 index 0000000..c7ea886 --- /dev/null +++ b/modules/backend/assets/ui/js/ajax/Handler.js @@ -0,0 +1,130 @@ +import { delegate } from 'jquery-events-to-dom-events'; + +/** + * Backend AJAX handler. + * + * This is a utility script that resolves some backwards-compatibility issues with the functionality + * that relies on the old framework, and ensures that Snowboard works well within the Backend + * environment. + * + * Functions: + * - Adds the "render" jQuery event to Snowboard requests that widgets use to initialise. + * - Ensures the CSRF token is included in requests. + * + * @copyright 2021 Winter. + * @author Ben Thomson + */ +export default class Handler extends Snowboard.Singleton { + /** + * Event listeners. + * + * @returns {Object} + */ + listens() { + return { + ready: 'ready', + ajaxFetchOptions: 'ajaxFetchOptions', + ajaxUpdateComplete: 'ajaxUpdateComplete', + }; + } + + /** + * Ready handler. + * + * Fires off a "render" event. + */ + ready() { + if (!window.jQuery) { + return; + } + delegate('render'); + + // Add global event for rendering in Snowboard + delegate('render'); + document.addEventListener('$render', () => { + this.snowboard.globalEvent('render'); + }); + + // Add "render" event for backwards compatibility + window.jQuery(document).trigger('render'); + + // Add global event for rendering in Snowboard + document.addEventListener('$render', () => { + this.snowboard.globalEvent('render'); + }); + } + + /** + * Adds the jQuery AJAX prefilter that the old framework uses to inject the CSRF token in AJAX + * calls. + */ + addPrefilter() { + if (!window.jQuery) { + return; + } + + window.jQuery.ajaxPrefilter((options) => { + if (this.hasToken()) { + if (!options.headers) { + options.headers = {}; + } + options.headers['X-CSRF-TOKEN'] = this.getToken(); + } + }); + } + + /** + * Fetch options handler. + * + * Ensures that the CSRF token is included in Snowboard requests. + * + * @param {Object} options + */ + ajaxFetchOptions(options) { + if (this.hasToken()) { + options.headers['X-CSRF-TOKEN'] = this.getToken(); + } + } + + /** + * Update complete handler. + * + * Fires off a "render" event when partials are updated so that any widgets included in + * responses are correctly initialised. + */ + ajaxUpdateComplete() { + if (!window.jQuery) { + return; + } + + // Add "render" event for backwards compatibility + window.jQuery(document).trigger('render'); + } + + /** + * Determines if a CSRF token is available. + * + * @returns {Boolean} + */ + hasToken() { + const tokenElement = document.querySelector('meta[name="csrf-token"]'); + + if (!tokenElement) { + return false; + } + if (!tokenElement.hasAttribute('content')) { + return false; + } + + return true; + } + + /** + * Gets the CSRF token. + * + * @returns {String} + */ + getToken() { + return document.querySelector('meta[name="csrf-token"]').getAttribute('content'); + } +} diff --git a/modules/backend/assets/ui/js/build/backend.js b/modules/backend/assets/ui/js/build/backend.js new file mode 100644 index 0000000..fc5e4ef --- /dev/null +++ b/modules/backend/assets/ui/js/build/backend.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunk_wintercms_wn_backend_module=self.webpackChunk_wintercms_wn_backend_module||[]).push([[476],{286:function(e,t,n){var i=n(35),r=n(171);class s extends Snowboard.Singleton{listens(){return{ready:"ready",ajaxFetchOptions:"ajaxFetchOptions",ajaxUpdateComplete:"ajaxUpdateComplete"}}ready(){window.jQuery&&((0,r.M)("render"),(0,r.M)("render"),document.addEventListener("$render",()=>{this.snowboard.globalEvent("render")}),window.jQuery(document).trigger("render"),document.addEventListener("$render",()=>{this.snowboard.globalEvent("render")}))}addPrefilter(){window.jQuery&&window.jQuery.ajaxPrefilter(e=>{this.hasToken()&&(e.headers||(e.headers={}),e.headers["X-CSRF-TOKEN"]=this.getToken())})}ajaxFetchOptions(e){this.hasToken()&&(e.headers["X-CSRF-TOKEN"]=this.getToken())}ajaxUpdateComplete(){window.jQuery&&window.jQuery(document).trigger("render")}hasToken(){const e=document.querySelector('meta[name="csrf-token"]');return!!e&&!!e.hasAttribute("content")}getToken(){return document.querySelector('meta[name="csrf-token"]').getAttribute("content")}}class a extends Snowboard.PluginBase{construct(e,t){if(e instanceof Snowboard.PluginBase==!1)throw new Error("Event handling can only be applied to Snowboard classes.");if(!t)throw new Error("Event prefix is required.");this.instance=e,this.eventPrefix=t,this.events=[]}on(e,t){this.events.push({event:e,callback:t})}off(e,t){this.events=this.events.filter(n=>n.event!==e||n.callback!==t)}once(e,t){const n=this.events.push({event:e,callback:(...e)=>{t(...e),this.events.splice(n-1,1)}})}fire(e,...t){const n=this.events.filter(t=>t.event===e);let i=!1;n.forEach(e=>{i||!1===e.callback(...t)&&(i=!0)}),i||this.snowboard.globalEvent(`${this.eventPrefix}.${e}`,...t)}firePromise(e,...t){const n=this.events.filter(t=>t.event===e),i=n.filter(e=>null!==e,n.map(e=>e.callback(...t)));Promise.all(i).then(()=>{this.snowboard.globalPromiseEvent(`${this.eventPrefix}.${e}`,...t)})}}class o extends Snowboard.Singleton{construct(){this.registeredWidgets=[],this.elements=[],this.events={mutate:e=>this.onMutation(e)},this.observer=null}listens(){return{ready:"onReady",render:"onRender",ajaxUpdate:"onAjaxUpdate"}}register(e,t,n){this.registeredWidgets.push({control:e,widget:t,callback:n})}unregister(e){this.registeredWidgets=this.registeredWidgets.filter(t=>t.control!==e)}onReady(){this.initializeWidgets(document.body),this.observer||(this.observer=new MutationObserver(this.events.mutate),this.observer.observe(document.body,{childList:!0,subtree:!0}))}onRender(){this.initializeWidgets(document.body)}onAjaxUpdate(e){this.initializeWidgets(e)}initializeWidgets(e){this.registeredWidgets.forEach(t=>{const n=e.querySelectorAll(`[data-control="${t.control}"]:not([data-widget-initialized])`);n.length&&n.forEach(e=>{if(e.dataset.widgetInitialized)return;const n=this.snowboard[t.widget](e);this.elements.push({element:e,instance:n}),e.dataset.widgetInitialized=!0,this.snowboard.globalEvent("backend.widget.initialized",e,n),"function"==typeof t.callback&&t.callback(n,e)})})}getWidget(e){const t=this.elements.find(t=>t.element===e);return t?t.instance:null}onMutation(e){const t=e.filter(e=>e.removedNodes.length).map(e=>Array.from(e.removedNodes)).flat();t.length&&t.forEach(e=>{const t=this.elements.filter(t=>e.contains(t.element));t.length&&t.forEach(e=>{e.instance.destruct(),this.elements=this.elements.filter(t=>t!==e)})})}}if(void 0===window.Snowboard)throw new Error("Snowboard must be loaded in order to use the Backend UI.");(e=>{e.addPlugin("backend.ajax.handler",s),e.addPlugin("backend.ui.eventHandler",a),e.addPlugin("backend.ui.widgetHandler",o),e["backend.ajax.handler"]().addPrefilter(),window.AssetManager={load:(t,n)=>{e.assetLoader().load(t).then(()=>{n&&"function"==typeof n&&n()})}},window.assetManager=window.AssetManager})(window.Snowboard),window.Vue=i}},function(e){e.O(0,[810],function(){return t=286,e(e.s=t);var t});e.O()}]); \ No newline at end of file diff --git a/modules/backend/assets/ui/js/build/manifest.js b/modules/backend/assets/ui/js/build/manifest.js new file mode 100644 index 0000000..97118a3 --- /dev/null +++ b/modules/backend/assets/ui/js/build/manifest.js @@ -0,0 +1 @@ +!function(){"use strict";var n,e={},r={};function t(n){var o=r[n];if(void 0!==o)return o.exports;var i=r[n]={id:n,exports:{}};return e[n](i,i.exports,t),i.exports}t.m=e,n=[],t.O=function(e,r,o,i){if(!r){var u=1/0;for(l=0;l=i)&&Object.keys(t.O).every(function(n){return t.O[n](r[c])})?r.splice(c--,1):(f=!1,i0&&n[l-1][2]>i;l--)n[l]=n[l-1];n[l]=[r,o,i]},t.n=function(n){var e=n&&n.__esModule?function(){return n.default}:function(){return n};return t.d(e,{a:e}),e},t.d=function(n,e){for(var r in e)t.o(e,r)&&!t.o(n,r)&&Object.defineProperty(n,r,{enumerable:!0,get:e[r]})},t.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(n){if("object"==typeof window)return window}}(),t.o=function(n,e){return Object.prototype.hasOwnProperty.call(n,e)},t.r=function(n){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(n,"__esModule",{value:!0})},function(){var n={624:0};t.O.j=function(e){return 0===n[e]};var e=function(e,r){var o,i,u=r[0],f=r[1],c=r[2],a=0;if(u.some(function(e){return 0!==n[e]})){for(o in f)t.o(f,o)&&(t.m[o]=f[o]);if(c)var l=c(t)}for(e&&e(r);ae in t}n.r(r),n.d(r,{BaseTransition:function(){return xr},BaseTransitionPropsValidators:function(){return _r},Comment:function(){return Ci},DeprecationTypes:function(){return Fc},EffectScope:function(){return be},ErrorCodes:function(){return kn},ErrorTypeStrings:function(){return Oc},Fragment:function(){return Si},KeepAlive:function(){return no},ReactiveEffect:function(){return ke},Static:function(){return Ti},Suspense:function(){return mi},Teleport:function(){return dr},Text:function(){return xi},TrackOpTypes:function(){return fn},Transition:function(){return Gc},TransitionGroup:function(){return zl},TriggerOpTypes:function(){return dn},VueElement:function(){return Fl},assertNumber:function(){return Tn},callWithAsyncErrorHandling:function(){return An},callWithErrorHandling:function(){return wn},camelize:function(){return M},capitalize:function(){return L},cloneVNode:function(){return qi},compatUtils:function(){return $c},computed:function(){return kc},createApp:function(){return Ca},createBlock:function(){return Pi},createCommentVNode:function(){return Ki},createElementBlock:function(){return Mi},createElementVNode:function(){return Bi},createHydrationRenderer:function(){return Vs},createPropsRestProxy:function(){return es},createRenderer:function(){return Fs},createSSRApp:function(){return Ta},createSlots:function(){return Oo},createStaticVNode:function(){return zi},createTextVNode:function(){return Wi},createVNode:function(){return Ui},customRef:function(){return rn},defineAsyncComponent:function(){return Zr},defineComponent:function(){return Nr},defineCustomElement:function(){return Dl},defineEmits:function(){return Ho},defineExpose:function(){return jo},defineModel:function(){return zo},defineOptions:function(){return qo},defineProps:function(){return Uo},defineSSRCustomElement:function(){return Ll},defineSlots:function(){return Wo},devtools:function(){return Mc},effect:function(){return Fe},effectScope:function(){return Se},getCurrentInstance:function(){return rc},getCurrentScope:function(){return xe},getCurrentWatcher:function(){return gn},getTransitionRawChildren:function(){return Ar},guardReactiveProps:function(){return ji},h:function(){return Ec},handleError:function(){return Nn},hasInjectionContext:function(){return bs},hydrate:function(){return xa},hydrateOnIdle:function(){return Jr},hydrateOnInteraction:function(){return Xr},hydrateOnMediaQuery:function(){return Gr},hydrateOnVisible:function(){return Yr},initCustomFormatter:function(){return wc},initDirectivesForSSR:function(){return Aa},inject:function(){return _s},isMemoSame:function(){return Nc},isProxy:function(){return Ut},isReactive:function(){return Ft},isReadonly:function(){return Vt},isRef:function(){return zt},isRuntimeOnly:function(){return mc},isShallow:function(){return Bt},isVNode:function(){return Di},markRaw:function(){return jt},mergeDefaults:function(){return Qo},mergeModels:function(){return Zo},mergeProps:function(){return Xi},nextTick:function(){return $n},normalizeClass:function(){return X},normalizeProps:function(){return Q},normalizeStyle:function(){return z},onActivated:function(){return oo},onBeforeMount:function(){return po},onBeforeUnmount:function(){return vo},onBeforeUpdate:function(){return mo},onDeactivated:function(){return so},onErrorCaptured:function(){return xo},onMounted:function(){return ho},onRenderTracked:function(){return So},onRenderTriggered:function(){return bo},onScopeDispose:function(){return Ce},onServerPrefetch:function(){return _o},onUnmounted:function(){return yo},onUpdated:function(){return go},onWatcherCleanup:function(){return vn},openBlock:function(){return wi},popScopeId:function(){return Qn},provide:function(){return ys},proxyRefs:function(){return tn},pushScopeId:function(){return Xn},queuePostFlushCb:function(){return Bn},reactive:function(){return Mt},readonly:function(){return Dt},ref:function(){return Kt},registerRuntimeCompiler:function(){return hc},render:function(){return Sa},renderList:function(){return Ro},renderSlot:function(){return Mo},resolveComponent:function(){return ko},resolveDirective:function(){return Ao},resolveDynamicComponent:function(){return wo},resolveFilter:function(){return Lc},resolveTransitionHooks:function(){return Tr},setBlockTracking:function(){return Ri},setDevtoolsHook:function(){return Pc},setTransitionHooks:function(){return wr},shallowReactive:function(){return Pt},shallowReadonly:function(){return Lt},shallowRef:function(){return Jt},ssrContextKey:function(){return Ks},ssrUtils:function(){return Dc},stop:function(){return Ve},toDisplayString:function(){return he},toHandlerKey:function(){return $},toHandlers:function(){return Do},toRaw:function(){return Ht},toRef:function(){return ln},toRefs:function(){return on},toValue:function(){return Zt},transformVNodeArgs:function(){return $i},triggerRef:function(){return Xt},unref:function(){return Qt},useAttrs:function(){return Yo},useCssModule:function(){return Ul},useCssVars:function(){return ml},useHost:function(){return Vl},useId:function(){return Ir},useModel:function(){return ni},useSSRContext:function(){return Js},useShadowRoot:function(){return Bl},useSlots:function(){return Jo},useTemplateRef:function(){return Or},useTransitionState:function(){return vr},vModelCheckbox:function(){return ta},vModelDynamic:function(){return la},vModelRadio:function(){return ra},vModelSelect:function(){return oa},vModelText:function(){return ea},vShow:function(){return dl},version:function(){return Ic},warn:function(){return Rc},watch:function(){return Qs},watchEffect:function(){return Ys},watchPostEffect:function(){return Gs},watchSyncEffect:function(){return Xs},withAsyncContext:function(){return ts},withCtx:function(){return er},withDefaults:function(){return Ko},withDirectives:function(){return tr},withKeys:function(){return ma},withMemo:function(){return Ac},withModifiers:function(){return pa},withScopeId:function(){return Zn}});const s={},i=[],c=()=>{},l=()=>!1,a=e=>111===e.charCodeAt(0)&&110===e.charCodeAt(1)&&(e.charCodeAt(2)>122||e.charCodeAt(2)<97),u=e=>e.startsWith("onUpdate:"),f=Object.assign,d=(e,t)=>{const n=e.indexOf(t);n>-1&&e.splice(n,1)},p=Object.prototype.hasOwnProperty,h=(e,t)=>p.call(e,t),m=Array.isArray,g=e=>"[object Map]"===k(e),v=e=>"[object Set]"===k(e),y=e=>"[object Date]"===k(e),_=e=>"function"==typeof e,b=e=>"string"==typeof e,S=e=>"symbol"==typeof e,x=e=>null!==e&&"object"==typeof e,C=e=>(x(e)||_(e))&&_(e.then)&&_(e.catch),T=Object.prototype.toString,k=e=>T.call(e),E=e=>k(e).slice(8,-1),w=e=>"[object Object]"===k(e),A=e=>b(e)&&"NaN"!==e&&"-"!==e[0]&&""+parseInt(e,10)===e,N=o(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),I=o("bind,cloak,else-if,else,for,html,if,model,on,once,pre,show,slot,text,memo"),R=e=>{const t=Object.create(null);return n=>t[n]||(t[n]=e(n))},O=/-(\w)/g,M=R(e=>e.replace(O,(e,t)=>t?t.toUpperCase():"")),P=/\B([A-Z])/g,D=R(e=>e.replace(P,"-$1").toLowerCase()),L=R(e=>e.charAt(0).toUpperCase()+e.slice(1)),$=R(e=>e?`on${L(e)}`:""),F=(e,t)=>!Object.is(e,t),V=(e,...t)=>{for(let n=0;n{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:r,value:n})},U=e=>{const t=parseFloat(e);return isNaN(t)?e:t},H=e=>{const t=b(e)?Number(e):NaN;return isNaN(t)?e:t};let j;const q=()=>j||(j="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n.g?n.g:{});const W=o("Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,console,Error,Symbol");function z(e){if(m(e)){const t={};for(let n=0;n{if(e){const n=e.split(J);n.length>1&&(t[n[0].trim()]=n[1].trim())}}),t}function X(e){let t="";if(b(e))t=e;else if(m(e))for(let n=0;n?@[\\\]^`{|}~]/g;function ue(e,t){return e.replace(ae,e=>t?'"'===e?'\\\\\\"':`\\\\${e}`:`\\${e}`)}function fe(e,t){if(e===t)return!0;let n=y(e),r=y(t);if(n||r)return!(!n||!r)&&e.getTime()===t.getTime();if(n=S(e),r=S(t),n||r)return e===t;if(n=m(e),r=m(t),n||r)return!(!n||!r)&&function(e,t){if(e.length!==t.length)return!1;let n=!0;for(let r=0;n&&rfe(e,t))}const pe=e=>!(!e||!0!==e.__v_isRef),he=e=>b(e)?e:null==e?"":m(e)||x(e)&&(e.toString===T||!_(e.toString))?pe(e)?he(e.value):JSON.stringify(e,me,2):String(e),me=(e,t)=>pe(t)?me(e,t.value):g(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((e,[t,n],r)=>(e[ge(t,r)+" =>"]=n,e),{})}:v(t)?{[`Set(${t.size})`]:[...t.values()].map(e=>ge(e))}:S(t)?ge(t):!x(t)||m(t)||w(t)?t:String(t),ge=(e,t="")=>{var n;return S(e)?`Symbol(${null!=(n=e.description)?n:t})`:e};function ve(e){return null==e?"initial":"string"==typeof e?""===e?" ":e:("number"==typeof e&&Number.isFinite(e),String(e))}let ye,_e;class be{constructor(e=!1){this.detached=e,this._active=!0,this._on=0,this.effects=[],this.cleanups=[],this._isPaused=!1,this.parent=ye,!e&&ye&&(this.index=(ye.scopes||(ye.scopes=[])).push(this)-1)}get active(){return this._active}pause(){if(this._active){let e,t;if(this._isPaused=!0,this.scopes)for(e=0,t=this.scopes.length;e0&&0===--this._on&&(ye=this.prevScope,this.prevScope=void 0)}stop(e){if(this._active){let t,n;for(this._active=!1,t=0,n=this.effects.length;t0)return;if(we){let e=we;for(we=void 0;e;){const t=e.next;e.next=void 0,e.flags&=-9,e=t}}let e;for(;Ee;){let t=Ee;for(Ee=void 0;t;){const n=t.next;if(t.next=void 0,t.flags&=-9,1&t.flags)try{t.trigger()}catch(t){e||(e=t)}t=n}}if(e)throw e}function Oe(e){for(let t=e.deps;t;t=t.nextDep)t.version=-1,t.prevActiveLink=t.dep.activeLink,t.dep.activeLink=t}function Me(e){let t,n=e.depsTail,r=n;for(;r;){const e=r.prevDep;-1===r.version?(r===n&&(n=e),Le(r),$e(r)):t=r,r.dep.activeLink=r.prevActiveLink,r.prevActiveLink=void 0,r=e}e.deps=t,e.depsTail=n}function Pe(e){for(let t=e.deps;t;t=t.nextDep)if(t.dep.version!==t.version||t.dep.computed&&(De(t.dep.computed)||t.dep.version!==t.version))return!0;return!!e._dirty}function De(e){if(4&e.flags&&!(16&e.flags))return;if(e.flags&=-17,e.globalVersion===We)return;if(e.globalVersion=We,!e.isSSR&&128&e.flags&&(!e.deps&&!e._dirty||!Pe(e)))return;e.flags|=2;const t=e.dep,n=_e,r=Be;_e=e,Be=!0;try{Oe(e);const n=e.fn(e._value);(0===t.version||F(n,e._value))&&(e.flags|=128,e._value=n,t.version++)}catch(e){throw t.version++,e}finally{_e=n,Be=r,Me(e),e.flags&=-3}}function Le(e,t=!1){const{dep:n,prevSub:r,nextSub:o}=e;if(r&&(r.nextSub=o,e.prevSub=void 0),o&&(o.prevSub=r,e.nextSub=void 0),n.subs===e&&(n.subs=r,!r&&n.computed)){n.computed.flags&=-5;for(let e=n.computed.deps;e;e=e.nextDep)Le(e,!0)}t||--n.sc||!n.map||n.map.delete(n.key)}function $e(e){const{prevDep:t,nextDep:n}=e;t&&(t.nextDep=n,e.prevDep=void 0),n&&(n.prevDep=t,e.nextDep=void 0)}function Fe(e,t){e.effect instanceof ke&&(e=e.effect.fn);const n=new ke(e);t&&f(n,t);try{n.run()}catch(e){throw n.stop(),e}const r=n.run.bind(n);return r.effect=n,r}function Ve(e){e.effect.stop()}let Be=!0;const Ue=[];function He(){Ue.push(Be),Be=!1}function je(){const e=Ue.pop();Be=void 0===e||e}function qe(e){const{cleanup:t}=e;if(e.cleanup=void 0,t){const e=_e;_e=void 0;try{t()}finally{_e=e}}}let We=0;class ze{constructor(e,t){this.sub=e,this.dep=t,this.version=t.version,this.nextDep=this.prevDep=this.nextSub=this.prevSub=this.prevActiveLink=void 0}}class Ke{constructor(e){this.computed=e,this.version=0,this.activeLink=void 0,this.subs=void 0,this.map=void 0,this.key=void 0,this.sc=0,this.__v_skip=!0}track(e){if(!_e||!Be||_e===this.computed)return;let t=this.activeLink;if(void 0===t||t.sub!==_e)t=this.activeLink=new ze(_e,this),_e.deps?(t.prevDep=_e.depsTail,_e.depsTail.nextDep=t,_e.depsTail=t):_e.deps=_e.depsTail=t,Je(t);else if(-1===t.version&&(t.version=this.version,t.nextDep)){const e=t.nextDep;e.prevDep=t.prevDep,t.prevDep&&(t.prevDep.nextDep=e),t.prevDep=_e.depsTail,t.nextDep=void 0,_e.depsTail.nextDep=t,_e.depsTail=t,_e.deps===t&&(_e.deps=e)}return t}trigger(e){this.version++,We++,this.notify(e)}notify(e){Ie();try{0;for(let e=this.subs;e;e=e.prevSub)e.sub.notify()&&e.sub.dep.notify()}finally{Re()}}}function Je(e){if(e.dep.sc++,4&e.sub.flags){const t=e.dep.computed;if(t&&!e.dep.subs){t.flags|=20;for(let e=t.deps;e;e=e.nextDep)Je(e)}const n=e.dep.subs;n!==e&&(e.prevSub=n,n&&(n.nextSub=e)),e.dep.subs=e}}const Ye=new WeakMap,Ge=Symbol(""),Xe=Symbol(""),Qe=Symbol("");function Ze(e,t,n){if(Be&&_e){let t=Ye.get(e);t||Ye.set(e,t=new Map);let r=t.get(n);r||(t.set(n,r=new Ke),r.map=t,r.key=n),r.track()}}function et(e,t,n,r,o,s){const i=Ye.get(e);if(!i)return void We++;const c=e=>{e&&e.trigger()};if(Ie(),"clear"===t)i.forEach(c);else{const o=m(e),s=o&&A(n);if(o&&"length"===n){const e=Number(r);i.forEach((t,n)=>{("length"===n||n===Qe||!S(n)&&n>=e)&&c(t)})}else switch((void 0!==n||i.has(void 0))&&c(i.get(n)),s&&c(i.get(Qe)),t){case"add":o?s&&c(i.get("length")):(c(i.get(Ge)),g(e)&&c(i.get(Xe)));break;case"delete":o||(c(i.get(Ge)),g(e)&&c(i.get(Xe)));break;case"set":g(e)&&c(i.get(Ge))}}Re()}function tt(e){const t=Ht(e);return t===e?t:(Ze(t,0,Qe),Bt(e)?t:t.map(qt))}function nt(e){return Ze(e=Ht(e),0,Qe),e}const rt={__proto__:null,[Symbol.iterator](){return ot(this,Symbol.iterator,qt)},concat(...e){return tt(this).concat(...e.map(e=>m(e)?tt(e):e))},entries(){return ot(this,"entries",e=>(e[1]=qt(e[1]),e))},every(e,t){return it(this,"every",e,t,void 0,arguments)},filter(e,t){return it(this,"filter",e,t,e=>e.map(qt),arguments)},find(e,t){return it(this,"find",e,t,qt,arguments)},findIndex(e,t){return it(this,"findIndex",e,t,void 0,arguments)},findLast(e,t){return it(this,"findLast",e,t,qt,arguments)},findLastIndex(e,t){return it(this,"findLastIndex",e,t,void 0,arguments)},forEach(e,t){return it(this,"forEach",e,t,void 0,arguments)},includes(...e){return lt(this,"includes",e)},indexOf(...e){return lt(this,"indexOf",e)},join(e){return tt(this).join(e)},lastIndexOf(...e){return lt(this,"lastIndexOf",e)},map(e,t){return it(this,"map",e,t,void 0,arguments)},pop(){return at(this,"pop")},push(...e){return at(this,"push",e)},reduce(e,...t){return ct(this,"reduce",e,t)},reduceRight(e,...t){return ct(this,"reduceRight",e,t)},shift(){return at(this,"shift")},some(e,t){return it(this,"some",e,t,void 0,arguments)},splice(...e){return at(this,"splice",e)},toReversed(){return tt(this).toReversed()},toSorted(e){return tt(this).toSorted(e)},toSpliced(...e){return tt(this).toSpliced(...e)},unshift(...e){return at(this,"unshift",e)},values(){return ot(this,"values",qt)}};function ot(e,t,n){const r=nt(e),o=r[t]();return r===e||Bt(e)||(o._next=o.next,o.next=()=>{const e=o._next();return e.value&&(e.value=n(e.value)),e}),o}const st=Array.prototype;function it(e,t,n,r,o,s){const i=nt(e),c=i!==e&&!Bt(e),l=i[t];if(l!==st[t]){const t=l.apply(e,s);return c?qt(t):t}let a=n;i!==e&&(c?a=function(t,r){return n.call(this,qt(t),r,e)}:n.length>2&&(a=function(t,r){return n.call(this,t,r,e)}));const u=l.call(i,a,r);return c&&o?o(u):u}function ct(e,t,n,r){const o=nt(e);let s=n;return o!==e&&(Bt(e)?n.length>3&&(s=function(t,r,o){return n.call(this,t,r,o,e)}):s=function(t,r,o){return n.call(this,t,qt(r),o,e)}),o[t](s,...r)}function lt(e,t,n){const r=Ht(e);Ze(r,0,Qe);const o=r[t](...n);return-1!==o&&!1!==o||!Ut(n[0])?o:(n[0]=Ht(n[0]),r[t](...n))}function at(e,t,n=[]){He(),Ie();const r=Ht(e)[t].apply(e,n);return Re(),je(),r}const ut=o("__proto__,__v_isRef,__isVue"),ft=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>"arguments"!==e&&"caller"!==e).map(e=>Symbol[e]).filter(S));function dt(e){S(e)||(e=String(e));const t=Ht(this);return Ze(t,0,e),t.hasOwnProperty(e)}class pt{constructor(e=!1,t=!1){this._isReadonly=e,this._isShallow=t}get(e,t,n){if("__v_skip"===t)return e.__v_skip;const r=this._isReadonly,o=this._isShallow;if("__v_isReactive"===t)return!r;if("__v_isReadonly"===t)return r;if("__v_isShallow"===t)return o;if("__v_raw"===t)return n===(r?o?Ot:Rt:o?It:Nt).get(e)||Object.getPrototypeOf(e)===Object.getPrototypeOf(n)?e:void 0;const s=m(e);if(!r){let e;if(s&&(e=rt[t]))return e;if("hasOwnProperty"===t)return dt}const i=Reflect.get(e,t,zt(e)?e:n);return(S(t)?ft.has(t):ut(t))?i:(r||Ze(e,0,t),o?i:zt(i)?s&&A(t)?i:i.value:x(i)?r?Dt(i):Mt(i):i)}}class ht extends pt{constructor(e=!1){super(!1,e)}set(e,t,n,r){let o=e[t];if(!this._isShallow){const t=Vt(o);if(Bt(n)||Vt(n)||(o=Ht(o),n=Ht(n)),!m(e)&&zt(o)&&!zt(n))return!t&&(o.value=n,!0)}const s=m(e)&&A(t)?Number(t)e,St=e=>Reflect.getPrototypeOf(e);function xt(e){return function(...t){return"delete"!==e&&("clear"===e?void 0:this)}}function Ct(e,t){const n={get(n){const r=this.__v_raw,o=Ht(r),s=Ht(n);e||(F(n,s)&&Ze(o,0,n),Ze(o,0,s));const{has:i}=St(o),c=t?bt:e?Wt:qt;return i.call(o,n)?c(r.get(n)):i.call(o,s)?c(r.get(s)):void(r!==o&&r.get(n))},get size(){const t=this.__v_raw;return!e&&Ze(Ht(t),0,Ge),Reflect.get(t,"size",t)},has(t){const n=this.__v_raw,r=Ht(n),o=Ht(t);return e||(F(t,o)&&Ze(r,0,t),Ze(r,0,o)),t===o?n.has(t):n.has(t)||n.has(o)},forEach(n,r){const o=this,s=o.__v_raw,i=Ht(s),c=t?bt:e?Wt:qt;return!e&&Ze(i,0,Ge),s.forEach((e,t)=>n.call(r,c(e),c(t),o))}};f(n,e?{add:xt("add"),set:xt("set"),delete:xt("delete"),clear:xt("clear")}:{add(e){t||Bt(e)||Vt(e)||(e=Ht(e));const n=Ht(this);return St(n).has.call(n,e)||(n.add(e),et(n,"add",e,e)),this},set(e,n){t||Bt(n)||Vt(n)||(n=Ht(n));const r=Ht(this),{has:o,get:s}=St(r);let i=o.call(r,e);i||(e=Ht(e),i=o.call(r,e));const c=s.call(r,e);return r.set(e,n),i?F(n,c)&&et(r,"set",e,n):et(r,"add",e,n),this},delete(e){const t=Ht(this),{has:n,get:r}=St(t);let o=n.call(t,e);o||(e=Ht(e),o=n.call(t,e));r&&r.call(t,e);const s=t.delete(e);return o&&et(t,"delete",e,void 0),s},clear(){const e=Ht(this),t=0!==e.size,n=e.clear();return t&&et(e,"clear",void 0,void 0),n}});return["keys","values","entries",Symbol.iterator].forEach(r=>{n[r]=function(e,t,n){return function(...r){const o=this.__v_raw,s=Ht(o),i=g(s),c="entries"===e||e===Symbol.iterator&&i,l="keys"===e&&i,a=o[e](...r),u=n?bt:t?Wt:qt;return!t&&Ze(s,0,l?Xe:Ge),{next(){const{value:e,done:t}=a.next();return t?{value:e,done:t}:{value:c?[u(e[0]),u(e[1])]:u(e),done:t}},[Symbol.iterator](){return this}}}}(r,e,t)}),n}function Tt(e,t){const n=Ct(e,t);return(t,r,o)=>"__v_isReactive"===r?!e:"__v_isReadonly"===r?e:"__v_raw"===r?t:Reflect.get(h(n,r)&&r in t?n:t,r,o)}const kt={get:Tt(!1,!1)},Et={get:Tt(!1,!0)},wt={get:Tt(!0,!1)},At={get:Tt(!0,!0)};const Nt=new WeakMap,It=new WeakMap,Rt=new WeakMap,Ot=new WeakMap;function Mt(e){return Vt(e)?e:$t(e,!1,gt,kt,Nt)}function Pt(e){return $t(e,!1,yt,Et,It)}function Dt(e){return $t(e,!0,vt,wt,Rt)}function Lt(e){return $t(e,!0,_t,At,Ot)}function $t(e,t,n,r,o){if(!x(e))return e;if(e.__v_raw&&(!t||!e.__v_isReactive))return e;const s=(i=e).__v_skip||!Object.isExtensible(i)?0:function(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}(E(i));var i;if(0===s)return e;const c=o.get(e);if(c)return c;const l=new Proxy(e,2===s?r:n);return o.set(e,l),l}function Ft(e){return Vt(e)?Ft(e.__v_raw):!(!e||!e.__v_isReactive)}function Vt(e){return!(!e||!e.__v_isReadonly)}function Bt(e){return!(!e||!e.__v_isShallow)}function Ut(e){return!!e&&!!e.__v_raw}function Ht(e){const t=e&&e.__v_raw;return t?Ht(t):e}function jt(e){return!h(e,"__v_skip")&&Object.isExtensible(e)&&B(e,"__v_skip",!0),e}const qt=e=>x(e)?Mt(e):e,Wt=e=>x(e)?Dt(e):e;function zt(e){return!!e&&!0===e.__v_isRef}function Kt(e){return Yt(e,!1)}function Jt(e){return Yt(e,!0)}function Yt(e,t){return zt(e)?e:new Gt(e,t)}class Gt{constructor(e,t){this.dep=new Ke,this.__v_isRef=!0,this.__v_isShallow=!1,this._rawValue=t?e:Ht(e),this._value=t?e:qt(e),this.__v_isShallow=t}get value(){return this.dep.track(),this._value}set value(e){const t=this._rawValue,n=this.__v_isShallow||Bt(e)||Vt(e);e=n?e:Ht(e),F(e,t)&&(this._rawValue=e,this._value=n?e:qt(e),this.dep.trigger())}}function Xt(e){e.dep&&e.dep.trigger()}function Qt(e){return zt(e)?e.value:e}function Zt(e){return _(e)?e():Qt(e)}const en={get:(e,t,n)=>"__v_raw"===t?e:Qt(Reflect.get(e,t,n)),set:(e,t,n,r)=>{const o=e[t];return zt(o)&&!zt(n)?(o.value=n,!0):Reflect.set(e,t,n,r)}};function tn(e){return Ft(e)?e:new Proxy(e,en)}class nn{constructor(e){this.__v_isRef=!0,this._value=void 0;const t=this.dep=new Ke,{get:n,set:r}=e(t.track.bind(t),t.trigger.bind(t));this._get=n,this._set=r}get value(){return this._value=this._get()}set value(e){this._set(e)}}function rn(e){return new nn(e)}function on(e){const t=m(e)?new Array(e.length):{};for(const n in e)t[n]=an(e,n);return t}class sn{constructor(e,t,n){this._object=e,this._key=t,this._defaultValue=n,this.__v_isRef=!0,this._value=void 0}get value(){const e=this._object[this._key];return this._value=void 0===e?this._defaultValue:e}set value(e){this._object[this._key]=e}get dep(){return function(e,t){const n=Ye.get(e);return n&&n.get(t)}(Ht(this._object),this._key)}}class cn{constructor(e){this._getter=e,this.__v_isRef=!0,this.__v_isReadonly=!0,this._value=void 0}get value(){return this._value=this._getter()}}function ln(e,t,n){return zt(e)?e:_(e)?new cn(e):x(e)&&arguments.length>1?an(e,t,n):Kt(e)}function an(e,t,n){const r=e[t];return zt(r)?r:new sn(e,t,n)}class un{constructor(e,t,n){this.fn=e,this.setter=t,this._value=void 0,this.dep=new Ke(this),this.__v_isRef=!0,this.deps=void 0,this.depsTail=void 0,this.flags=16,this.globalVersion=We-1,this.next=void 0,this.effect=this,this.__v_isReadonly=!t,this.isSSR=n}notify(){if(this.flags|=16,!(8&this.flags||_e===this))return Ne(this,!0),!0}get value(){const e=this.dep.track();return De(this),e&&(e.version=this.dep.version),this._value}set value(e){this.setter&&this.setter(e)}}const fn={GET:"get",HAS:"has",ITERATE:"iterate"},dn={SET:"set",ADD:"add",DELETE:"delete",CLEAR:"clear"},pn={},hn=new WeakMap;let mn;function gn(){return mn}function vn(e,t=!1,n=mn){if(n){let t=hn.get(n);t||hn.set(n,t=[]),t.push(e)}else 0}function yn(e,t=1/0,n){if(t<=0||!x(e)||e.__v_skip)return e;if((n=n||new Set).has(e))return e;if(n.add(e),t--,zt(e))yn(e.value,t,n);else if(m(e))for(let r=0;r{yn(e,t,n)});else if(w(e)){for(const r in e)yn(e[r],t,n);for(const r of Object.getOwnPropertySymbols(e))Object.prototype.propertyIsEnumerable.call(e,r)&&yn(e[r],t,n)}return e} +/** +* @vue/runtime-core v3.5.18 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/ +const _n=[];let bn=!1;function Sn(e,...t){if(bn)return;bn=!0,He();const n=_n.length?_n[_n.length-1].component:null,r=n&&n.appContext.config.warnHandler,o=function(){let e=_n[_n.length-1];if(!e)return[];const t=[];for(;e;){const n=t[0];n&&n.vnode===e?n.recurseCount++:t.push({vnode:e,recurseCount:0});const r=e.component&&e.component.parent;e=r&&r.vnode}return t}();if(r)wn(r,n,11,[e+t.map(e=>{var t,n;return null!=(n=null==(t=e.toString)?void 0:t.call(e))?n:JSON.stringify(e)}).join(""),n&&n.proxy,o.map(({vnode:e})=>`at <${Cc(n,e.type)}>`).join("\n"),o]);else{const n=[`[Vue warn]: ${e}`,...t];o.length&&n.push("\n",...function(e){const t=[];return e.forEach((e,n)=>{t.push(...0===n?[]:["\n"],...function({vnode:e,recurseCount:t}){const n=t>0?`... (${t} recursive calls)`:"",r=!!e.component&&null==e.component.parent,o=` at <${Cc(e.component,e.type,r)}`,s=">"+n;return e.props?[o,...xn(e.props),s]:[o+s]}(e))}),t}(o)),console.warn(...n)}je(),bn=!1}function xn(e){const t=[],n=Object.keys(e);return n.slice(0,3).forEach(n=>{t.push(...Cn(n,e[n]))}),n.length>3&&t.push(" ..."),t}function Cn(e,t,n){return b(t)?(t=JSON.stringify(t),n?t:[`${e}=${t}`]):"number"==typeof t||"boolean"==typeof t||null==t?n?t:[`${e}=${t}`]:zt(t)?(t=Cn(e,Ht(t.value),!0),n?t:[`${e}=Ref<`,t,">"]):_(t)?[`${e}=fn${t.name?`<${t.name}>`:""}`]:(t=Ht(t),n?t:[`${e}=`,t])}function Tn(e,t){}const kn={SETUP_FUNCTION:0,0:"SETUP_FUNCTION",RENDER_FUNCTION:1,1:"RENDER_FUNCTION",NATIVE_EVENT_HANDLER:5,5:"NATIVE_EVENT_HANDLER",COMPONENT_EVENT_HANDLER:6,6:"COMPONENT_EVENT_HANDLER",VNODE_HOOK:7,7:"VNODE_HOOK",DIRECTIVE_HOOK:8,8:"DIRECTIVE_HOOK",TRANSITION_HOOK:9,9:"TRANSITION_HOOK",APP_ERROR_HANDLER:10,10:"APP_ERROR_HANDLER",APP_WARN_HANDLER:11,11:"APP_WARN_HANDLER",FUNCTION_REF:12,12:"FUNCTION_REF",ASYNC_COMPONENT_LOADER:13,13:"ASYNC_COMPONENT_LOADER",SCHEDULER:14,14:"SCHEDULER",COMPONENT_UPDATE:15,15:"COMPONENT_UPDATE",APP_UNMOUNT_CLEANUP:16,16:"APP_UNMOUNT_CLEANUP"},En={sp:"serverPrefetch hook",bc:"beforeCreate hook",c:"created hook",bm:"beforeMount hook",m:"mounted hook",bu:"beforeUpdate hook",u:"updated",bum:"beforeUnmount hook",um:"unmounted hook",a:"activated hook",da:"deactivated hook",ec:"errorCaptured hook",rtc:"renderTracked hook",rtg:"renderTriggered hook",0:"setup function",1:"render function",2:"watcher getter",3:"watcher callback",4:"watcher cleanup function",5:"native event handler",6:"component event handler",7:"vnode hook",8:"directive hook",9:"transition hook",10:"app errorHandler",11:"app warnHandler",12:"ref function",13:"async component loader",14:"scheduler flush",15:"component update",16:"app unmount cleanup function"};function wn(e,t,n,r){try{return r?e(...r):e()}catch(e){Nn(e,t,n)}}function An(e,t,n,r){if(_(e)){const o=wn(e,t,n,r);return o&&C(o)&&o.catch(e=>{Nn(e,t,n)}),o}if(m(e)){const o=[];for(let s=0;s=jn(n)?In.push(e):In.splice(function(e){let t=Rn+1,n=In.length;for(;t>>1,o=In[r],s=jn(o);sjn(e)-jn(t));if(On.length=0,Mn)return void Mn.push(...e);for(Mn=e,Pn=0;Pnnull==e.id?2&e.flags?-1:1/0:e.id;function qn(e){try{for(Rn=0;Rner;function er(e,t=Jn,n){if(!t)return e;if(e._n)return e;const r=(...n)=>{r._d&&Ri(-1);const o=Gn(t);let s;try{s=e(...n)}finally{Gn(o),r._d&&Ri(1)}return s};return r._n=!0,r._c=!0,r._d=!0,r}function tr(e,t){if(null===Jn)return e;const n=_c(Jn),r=e.dirs||(e.dirs=[]);for(let e=0;ee.__isTeleport,sr=e=>e&&(e.disabled||""===e.disabled),ir=e=>e&&(e.defer||""===e.defer),cr=e=>"undefined"!=typeof SVGElement&&e instanceof SVGElement,lr=e=>"function"==typeof MathMLElement&&e instanceof MathMLElement,ar=(e,t)=>{const n=e&&e.to;if(b(n)){if(t){return t(n)}return null}return n},ur={name:"Teleport",__isTeleport:!0,process(e,t,n,r,o,s,i,c,l,a){const{mc:u,pc:f,pbc:d,o:{insert:p,querySelector:h,createText:m,createComment:g}}=a,v=sr(t.props);let{shapeFlag:y,children:_,dynamicChildren:b}=t;if(null==e){const e=t.el=m(""),a=t.anchor=m("");p(e,n,r),p(a,n,r);const f=(e,t)=>{16&y&&(o&&o.isCE&&(o.ce._teleportTarget=e),u(_,e,t,o,s,i,c,l))},d=()=>{const e=t.target=ar(t.props,h),n=hr(e,t,m,p);e&&("svg"!==i&&cr(e)?i="svg":"mathml"!==i&&lr(e)&&(i="mathml"),v||(f(e,n),pr(t,!1)))};v&&(f(n,a),pr(t,!0)),ir(t.props)?(t.el.__isMounted=!1,$s(()=>{d(),delete t.el.__isMounted},s)):d()}else{if(ir(t.props)&&!1===e.el.__isMounted)return void $s(()=>{ur.process(e,t,n,r,o,s,i,c,l,a)},s);t.el=e.el,t.targetStart=e.targetStart;const u=t.anchor=e.anchor,p=t.target=e.target,m=t.targetAnchor=e.targetAnchor,g=sr(e.props),y=g?n:p,_=g?u:m;if("svg"===i||cr(p)?i="svg":("mathml"===i||lr(p))&&(i="mathml"),b?(d(e.dynamicChildren,b,y,o,s,i,c),qs(e,t,!0)):l||f(e,t,y,_,o,s,i,c,!1),v)g?t.props&&e.props&&t.props.to!==e.props.to&&(t.props.to=e.props.to):fr(t,n,u,a,1);else if((t.props&&t.props.to)!==(e.props&&e.props.to)){const e=t.target=ar(t.props,h);e&&fr(t,e,null,a,0)}else g&&fr(t,p,m,a,1);pr(t,v)}},remove(e,t,n,{um:r,o:{remove:o}},s){const{shapeFlag:i,children:c,anchor:l,targetStart:a,targetAnchor:u,target:f,props:d}=e;if(f&&(o(a),o(u)),s&&o(l),16&i){const e=s||!sr(d);for(let o=0;o{e.isMounted=!0}),vo(()=>{e.isUnmounting=!0}),e}const yr=[Function,Array],_r={mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:yr,onEnter:yr,onAfterEnter:yr,onEnterCancelled:yr,onBeforeLeave:yr,onLeave:yr,onAfterLeave:yr,onLeaveCancelled:yr,onBeforeAppear:yr,onAppear:yr,onAfterAppear:yr,onAppearCancelled:yr},br=e=>{const t=e.subTree;return t.component?br(t.component):t};function Sr(e){let t=e[0];if(e.length>1){let n=!1;for(const r of e)if(r.type!==Ci){0,t=r,n=!0;break}}return t}const xr={name:"BaseTransition",props:_r,setup(e,{slots:t}){const n=rc(),r=vr();return()=>{const o=t.default&&Ar(t.default(),!0);if(!o||!o.length)return;const s=Sr(o),i=Ht(e),{mode:c}=i;if(r.isLeaving)return kr(s);const l=Er(s);if(!l)return kr(s);let a=Tr(l,i,r,n,e=>a=e);l.type!==Ci&&wr(l,a);let u=n.subTree&&Er(n.subTree);if(u&&u.type!==Ci&&!Li(l,u)&&br(n).type!==Ci){let e=Tr(u,i,r,n);if(wr(u,e),"out-in"===c&&l.type!==Ci)return r.isLeaving=!0,e.afterLeave=()=>{r.isLeaving=!1,8&n.job.flags||n.update(),delete e.afterLeave,u=void 0},kr(s);"in-out"===c&&l.type!==Ci?e.delayLeave=(e,t,n)=>{Cr(r,u)[String(u.key)]=u,e[mr]=()=>{t(),e[mr]=void 0,delete a.delayedLeave,u=void 0},a.delayedLeave=()=>{n(),delete a.delayedLeave,u=void 0}}:u=void 0}else u&&(u=void 0);return s}}};function Cr(e,t){const{leavingVNodes:n}=e;let r=n.get(t.type);return r||(r=Object.create(null),n.set(t.type,r)),r}function Tr(e,t,n,r,o){const{appear:s,mode:i,persisted:c=!1,onBeforeEnter:l,onEnter:a,onAfterEnter:u,onEnterCancelled:f,onBeforeLeave:d,onLeave:p,onAfterLeave:h,onLeaveCancelled:g,onBeforeAppear:v,onAppear:y,onAfterAppear:_,onAppearCancelled:b}=t,S=String(e.key),x=Cr(n,e),C=(e,t)=>{e&&An(e,r,9,t)},T=(e,t)=>{const n=t[1];C(e,t),m(e)?e.every(e=>e.length<=1)&&n():e.length<=1&&n()},k={mode:i,persisted:c,beforeEnter(t){let r=l;if(!n.isMounted){if(!s)return;r=v||l}t[mr]&&t[mr](!0);const o=x[S];o&&Li(e,o)&&o.el[mr]&&o.el[mr](),C(r,[t])},enter(e){let t=a,r=u,o=f;if(!n.isMounted){if(!s)return;t=y||a,r=_||u,o=b||f}let i=!1;const c=e[gr]=t=>{i||(i=!0,C(t?o:r,[e]),k.delayedLeave&&k.delayedLeave(),e[gr]=void 0)};t?T(t,[e,c]):c()},leave(t,r){const o=String(e.key);if(t[gr]&&t[gr](!0),n.isUnmounting)return r();C(d,[t]);let s=!1;const i=t[mr]=n=>{s||(s=!0,r(),C(n?g:h,[t]),t[mr]=void 0,x[o]===e&&delete x[o])};x[o]=e,p?T(p,[t,i]):i()},clone(e){const s=Tr(e,t,n,r,o);return o&&o(s),s}};return k}function kr(e){if(to(e))return(e=qi(e)).children=null,e}function Er(e){if(!to(e))return or(e.type)&&e.children?Sr(e.children):e;if(e.component)return e.component.subTree;const{shapeFlag:t,children:n}=e;if(n){if(16&t)return n[0];if(32&t&&_(n.default))return n.default()}}function wr(e,t){6&e.shapeFlag&&e.component?(e.transition=t,wr(e.component.subTree,t)):128&e.shapeFlag?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Ar(e,t=!1,n){let r=[],o=0;for(let s=0;s1)for(let e=0;ef({name:e.name},t,{setup:e}))():e}function Ir(){const e=rc();return e?(e.appContext.config.idPrefix||"v")+"-"+e.ids[0]+e.ids[1]++:""}function Rr(e){e.ids=[e.ids[0]+e.ids[2]+++"-",0,0]}function Or(e){const t=rc(),n=Jt(null);if(t){const r=t.refs===s?t.refs={}:t.refs;Object.defineProperty(r,e,{enumerable:!0,get:()=>n.value,set:e=>n.value=e})}else 0;return n}function Mr(e,t,n,r,o=!1){if(m(e))return void e.forEach((e,s)=>Mr(e,t&&(m(t)?t[s]:t),n,r,o));if(Qr(r)&&!o)return void(512&r.shapeFlag&&r.type.__asyncResolved&&r.component.subTree.component&&Mr(e,t,n,r.component.subTree));const i=4&r.shapeFlag?_c(r.component):r.el,c=o?null:i,{i:l,r:a}=e;const u=t&&t.r,f=l.refs===s?l.refs={}:l.refs,p=l.setupState,g=Ht(p),v=p===s?()=>!1:e=>h(g,e);if(null!=u&&u!==a&&(b(u)?(f[u]=null,v(u)&&(p[u]=null)):zt(u)&&(u.value=null)),_(a))wn(a,l,12,[c,f]);else{const t=b(a),r=zt(a);if(t||r){const s=()=>{if(e.f){const n=t?v(a)?p[a]:f[a]:a.value;o?m(n)&&d(n,i):m(n)?n.includes(i)||n.push(i):t?(f[a]=[i],v(a)&&(p[a]=f[a])):(a.value=[i],e.k&&(f[e.k]=a.value))}else t?(f[a]=c,v(a)&&(p[a]=c)):r&&(a.value=c,e.k&&(f[e.k]=c))};c?(s.id=-1,$s(s,n)):s()}else 0}}let Pr=!1;const Dr=()=>{Pr||(console.error("Hydration completed but contains mismatches."),Pr=!0)},Lr=e=>{if(1===e.nodeType)return(e=>e.namespaceURI.includes("svg")&&"foreignObject"!==e.tagName)(e)?"svg":(e=>e.namespaceURI.includes("MathML"))(e)?"mathml":void 0},$r=e=>8===e.nodeType;function Fr(e){const{mt:t,p:n,o:{patchProp:r,createText:o,nextSibling:s,parentNode:i,remove:c,insert:l,createComment:u}}=e,f=(n,r,c,a,u,_=!1)=>{_=_||!!r.dynamicChildren;const b=$r(n)&&"["===n.data,S=()=>m(n,r,c,a,u,b),{type:x,ref:C,shapeFlag:T,patchFlag:k}=r;let E=n.nodeType;r.el=n,-2===k&&(_=!1,r.dynamicChildren=null);let w=null;switch(x){case xi:3!==E?""===r.children?(l(r.el=o(""),i(n),n),w=n):w=S():(n.data!==r.children&&(__VUE_PROD_HYDRATION_MISMATCH_DETAILS__&&Sn("Hydration text mismatch in",n.parentNode,`\n - rendered on server: ${JSON.stringify(n.data)}\n - expected on client: ${JSON.stringify(r.children)}`),Dr(),n.data=r.children),w=s(n));break;case Ci:y(n)?(w=s(n),v(r.el=n.content.firstChild,n,c)):w=8!==E||b?S():s(n);break;case Ti:if(b&&(E=(n=s(n)).nodeType),1===E||3===E){w=n;const e=!r.children.length;for(let t=0;t{i=i||!!t.dynamicChildren;const{type:l,props:u,patchFlag:f,shapeFlag:d,dirs:h,transition:m}=t,g="input"===l||"option"===l;if(g||-1!==f){h&&nr(t,null,n,"created");let l,_=!1;if(y(e)){_=js(null,m)&&n&&n.vnode.props&&n.vnode.props.appear;const r=e.content.firstChild;if(_){const e=r.getAttribute("class");e&&(r.$cls=e),m.beforeEnter(r)}v(r,e,n),t.el=e=r}if(16&d&&(!u||!u.innerHTML&&!u.textContent)){let r=p(e.firstChild,t,e,n,o,s,i),l=!1;for(;r;){Wr(e,1)||(__VUE_PROD_HYDRATION_MISMATCH_DETAILS__&&!l&&(Sn("Hydration children mismatch on",e,"\nServer rendered element contains more child nodes than client vdom."),l=!0),Dr());const t=r;r=r.nextSibling,c(t)}}else if(8&d){let n=t.children;"\n"!==n[0]||"PRE"!==e.tagName&&"TEXTAREA"!==e.tagName||(n=n.slice(1)),e.textContent!==n&&(Wr(e,0)||(__VUE_PROD_HYDRATION_MISMATCH_DETAILS__&&Sn("Hydration text content mismatch on",e,`\n - rendered on server: ${e.textContent}\n - expected on client: ${t.children}`),Dr()),e.textContent=t.children)}if(u)if(__VUE_PROD_HYDRATION_MISMATCH_DETAILS__||g||!i||48&f){const o=e.tagName.includes("-");for(const s in u)!__VUE_PROD_HYDRATION_MISMATCH_DETAILS__||h&&h.some(e=>e.dir.created)||!Vr(e,s,u[s],t,n)||Dr(),(g&&(s.endsWith("value")||"indeterminate"===s)||a(s)&&!N(s)||"."===s[0]||o)&&r(e,s,null,u[s],void 0,n)}else if(u.onClick)r(e,"onClick",null,u.onClick,void 0,n);else if(4&f&&Ft(u.style))for(const e in u.style)u.style[e];(l=u&&u.onVnodeBeforeMount)&&Qi(l,n,t),h&&nr(t,null,n,"beforeMount"),((l=u&&u.onVnodeMounted)||h||_)&&_i(()=>{l&&Qi(l,n,t),_&&m.enter(e),h&&nr(t,null,n,"mounted")},o)}return e.nextSibling},p=(e,t,r,i,c,a,u)=>{u=u||!!t.dynamicChildren;const d=t.children,p=d.length;let h=!1;for(let t=0;t{const{slotScopeIds:a}=t;a&&(o=o?o.concat(a):a);const f=i(e),d=p(s(e),t,f,n,r,o,c);return d&&$r(d)&&"]"===d.data?s(t.anchor=d):(Dr(),l(t.anchor=u("]"),f,d),d)},m=(e,t,r,o,l,a)=>{if(Wr(e.parentElement,1)||(__VUE_PROD_HYDRATION_MISMATCH_DETAILS__&&Sn("Hydration node mismatch:\n- rendered on server:",e,3===e.nodeType?"(text)":$r(e)&&"["===e.data?"(start of fragment)":"","\n- expected on client:",t.type),Dr()),t.el=null,a){const t=g(e);for(;;){const n=s(e);if(!n||n===t)break;c(n)}}const u=s(e),f=i(e);return c(e),n(null,t,f,u,r,o,Lr(f),l),r&&(r.vnode.el=t.el,di(r,t.el)),u},g=(e,t="[",n="]")=>{let r=0;for(;e;)if((e=s(e))&&$r(e)&&(e.data===t&&r++,e.data===n)){if(0===r)return s(e);r--}return e},v=(e,t,n)=>{const r=t.parentNode;r&&r.replaceChild(e,t);let o=n;for(;o;)o.vnode.el===t&&(o.vnode.el=o.subTree.el=e),o=o.parent},y=e=>1===e.nodeType&&"TEMPLATE"===e.tagName;return[(e,t)=>{if(!t.hasChildNodes())return __VUE_PROD_HYDRATION_MISMATCH_DETAILS__&&Sn("Attempting to hydrate existing markup but container is empty. Performing full mount instead."),n(null,e,t),Hn(),void(t._vnode=e);f(t.firstChild,e,null,null,null),Hn(),t._vnode=e},f]}function Vr(e,t,n,r,o){let s,i,c,l;if("class"===t)e.$cls?(c=e.$cls,delete e.$cls):c=e.getAttribute("class"),l=X(n),function(e,t){if(e.size!==t.size)return!1;for(const n of e)if(!t.has(n))return!1;return!0}(Br(c||""),Br(l))||(s=2,i="class");else if("style"===t){c=e.getAttribute("style")||"",l=b(n)?n:function(e){if(!e)return"";if(b(e))return e;let t="";for(const n in e){const r=e[n];(b(r)||"number"==typeof r)&&(t+=`${n.startsWith("--")?n:D(n)}:${r};`)}return t}(z(n));const t=Ur(c),a=Ur(l);if(r.dirs)for(const{dir:e,value:t}of r.dirs)"show"!==e.name||t||a.set("display","none");o&&Hr(o,r,a),function(e,t){if(e.size!==t.size)return!1;for(const[n,r]of e)if(r!==t.get(n))return!1;return!0}(t,a)||(s=3,i="style")}else(e instanceof SVGElement&&le(t)||e instanceof HTMLElement&&(se(t)||ce(t)))&&(se(t)?(c=e.hasAttribute(t),l=ie(n)):null==n?(c=e.hasAttribute(t),l=!1):(c=e.hasAttribute(t)?e.getAttribute(t):"value"===t&&"TEXTAREA"===e.tagName&&e.value,l=!!function(e){if(null==e)return!1;const t=typeof e;return"string"===t||"number"===t||"boolean"===t}(n)&&String(n)),c!==l&&(s=4,i=t));if(null!=s&&!Wr(e,s)){const t=e=>!1===e?"(not rendered)":`${i}="${e}"`;return Sn(`Hydration ${qr[s]} mismatch on`,e,`\n - rendered on server: ${t(c)}\n - expected on client: ${t(l)}\n Note: this mismatch is check-only. The DOM will not be rectified in production due to performance overhead.\n You should fix the source of the mismatch.`),!0}return!1}function Br(e){return new Set(e.trim().split(/\s+/))}function Ur(e){const t=new Map;for(const n of e.split(";")){let[e,r]=n.split(":");e=e.trim(),r=r&&r.trim(),e&&r&&t.set(e,r)}return t}function Hr(e,t,n){const r=e.subTree;if(e.getCssVars&&(t===r||r&&r.type===Si&&r.children.includes(t))){const t=e.getCssVars();for(const e in t){const r=ve(t[e]);n.set(`--${ue(e,!1)}`,r)}}t===r&&e.parent&&Hr(e.parent,e.vnode,n)}const jr="data-allow-mismatch",qr={0:"text",1:"children",2:"class",3:"style",4:"attribute"};function Wr(e,t){if(0===t||1===t)for(;e&&!e.hasAttribute(jr);)e=e.parentElement;const n=e&&e.getAttribute(jr);if(null==n)return!1;if(""===n)return!0;{const e=n.split(",");return!(0!==t||!e.includes("children"))||e.includes(qr[t])}}const zr=q().requestIdleCallback||(e=>setTimeout(e,1)),Kr=q().cancelIdleCallback||(e=>clearTimeout(e)),Jr=(e=1e4)=>t=>{const n=zr(t,{timeout:e});return()=>Kr(n)};const Yr=e=>(t,n)=>{const r=new IntersectionObserver(e=>{for(const n of e)if(n.isIntersecting){r.disconnect(),t();break}},e);return n(e=>{if(e instanceof Element)return function(e){const{top:t,left:n,bottom:r,right:o}=e.getBoundingClientRect(),{innerHeight:s,innerWidth:i}=window;return(t>0&&t0&&r0&&n0&&or.disconnect()},Gr=e=>t=>{if(e){const n=matchMedia(e);if(!n.matches)return n.addEventListener("change",t,{once:!0}),()=>n.removeEventListener("change",t);t()}},Xr=(e=[])=>(t,n)=>{b(e)&&(e=[e]);let r=!1;const o=e=>{r||(r=!0,s(),t(),e.target.dispatchEvent(new e.constructor(e.type,e)))},s=()=>{n(t=>{for(const n of e)t.removeEventListener(n,o)})};return n(t=>{for(const n of e)t.addEventListener(n,o,{once:!0})}),s};const Qr=e=>!!e.type.__asyncLoader; +/*! #__NO_SIDE_EFFECTS__ */function Zr(e){_(e)&&(e={loader:e});const{loader:t,loadingComponent:n,errorComponent:r,delay:o=200,hydrate:s,timeout:i,suspensible:c=!0,onError:l}=e;let a,u=null,f=0;const d=()=>{let e;return u||(e=u=t().catch(e=>{if(e=e instanceof Error?e:new Error(String(e)),l)return new Promise((t,n)=>{l(e,()=>t((f++,u=null,d())),()=>n(e),f+1)});throw e}).then(t=>e!==u&&u?u:(t&&(t.__esModule||"Module"===t[Symbol.toStringTag])&&(t=t.default),a=t,t)))};return Nr({name:"AsyncComponentWrapper",__asyncLoader:d,__asyncHydrate(e,t,n){let r=!1;(t.bu||(t.bu=[])).push(()=>r=!0);const o=()=>{r||n()},i=s?()=>{const n=s(o,t=>function(e,t){if($r(e)&&"["===e.data){let n=1,r=e.nextSibling;for(;r;){if(1===r.nodeType){if(!1===t(r))break}else if($r(r))if("]"===r.data){if(0===--n)break}else"["===r.data&&n++;r=r.nextSibling}}else t(e)}(e,t));n&&(t.bum||(t.bum=[])).push(n)}:o;a?i():d().then(()=>!t.isUnmounted&&i())},get __asyncResolved(){return a},setup(){const e=nc;if(Rr(e),a)return()=>eo(a,e);const t=t=>{u=null,Nn(t,e,13,!r)};if(c&&e.suspense||fc)return d().then(t=>()=>eo(t,e)).catch(e=>(t(e),()=>r?Ui(r,{error:e}):null));const s=Kt(!1),l=Kt(),f=Kt(!!o);return o&&setTimeout(()=>{f.value=!1},o),null!=i&&setTimeout(()=>{if(!s.value&&!l.value){const e=new Error(`Async component timed out after ${i}ms.`);t(e),l.value=e}},i),d().then(()=>{s.value=!0,e.parent&&to(e.parent.vnode)&&e.parent.update()}).catch(e=>{t(e),l.value=e}),()=>s.value&&a?eo(a,e):l.value&&r?Ui(r,{error:l.value}):n&&!f.value?Ui(n):void 0}})}function eo(e,t){const{ref:n,props:r,children:o,ce:s}=t.vnode,i=Ui(e,r,o);return i.ref=n,i.ce=s,delete t.vnode.ce,i}const to=e=>e.type.__isKeepAlive,no={name:"KeepAlive",__isKeepAlive:!0,props:{include:[String,RegExp,Array],exclude:[String,RegExp,Array],max:[String,Number]},setup(e,{slots:t}){const n=rc(),r=n.ctx;if(!r.renderer)return()=>{const e=t.default&&t.default();return e&&1===e.length?e[0]:e};const o=new Map,s=new Set;let i=null;const c=n.suspense,{renderer:{p:l,m:a,um:u,o:{createElement:f}}}=r,d=f("div");function p(e){lo(e),u(e,n,c,!0)}function h(e){o.forEach((t,n)=>{const r=xc(t.type);r&&!e(r)&&m(n)})}function m(e){const t=o.get(e);!t||i&&Li(t,i)?i&&lo(i):p(t),o.delete(e),s.delete(e)}r.activate=(e,t,n,r,o)=>{const s=e.component;a(e,t,n,0,c),l(s.vnode,e,t,n,s,c,r,e.slotScopeIds,o),$s(()=>{s.isDeactivated=!1,s.a&&V(s.a);const t=e.props&&e.props.onVnodeMounted;t&&Qi(t,s.parent,e)},c)},r.deactivate=e=>{const t=e.component;zs(t.m),zs(t.a),a(e,d,null,1,c),$s(()=>{t.da&&V(t.da);const n=e.props&&e.props.onVnodeUnmounted;n&&Qi(n,t.parent,e),t.isDeactivated=!0},c)},Qs(()=>[e.include,e.exclude],([e,t])=>{e&&h(t=>ro(e,t)),t&&h(e=>!ro(t,e))},{flush:"post",deep:!0});let g=null;const v=()=>{null!=g&&(pi(n.subTree.type)?$s(()=>{o.set(g,ao(n.subTree))},n.subTree.suspense):o.set(g,ao(n.subTree)))};return ho(v),go(v),vo(()=>{o.forEach(e=>{const{subTree:t,suspense:r}=n,o=ao(t);if(e.type===o.type&&e.key===o.key){lo(o);const e=o.component.da;return void(e&&$s(e,r))}p(e)})}),()=>{if(g=null,!t.default)return i=null;const n=t.default(),r=n[0];if(n.length>1)return i=null,n;if(!(Di(r)&&(4&r.shapeFlag||128&r.shapeFlag)))return i=null,r;let c=ao(r);if(c.type===Ci)return i=null,c;const l=c.type,a=xc(Qr(c)?c.type.__asyncResolved||{}:l),{include:u,exclude:f,max:d}=e;if(u&&(!a||!ro(u,a))||f&&a&&ro(f,a))return c.shapeFlag&=-257,i=c,r;const p=null==c.key?l:c.key,h=o.get(p);return c.el&&(c=qi(c),128&r.shapeFlag&&(r.ssContent=c)),g=p,h?(c.el=h.el,c.component=h.component,c.transition&&wr(c,c.transition),c.shapeFlag|=512,s.delete(p),s.add(p)):(s.add(p),d&&s.size>parseInt(d,10)&&m(s.values().next().value)),c.shapeFlag|=256,i=c,pi(r.type)?r:c}}};function ro(e,t){return m(e)?e.some(e=>ro(e,t)):b(e)?e.split(",").includes(t):"[object RegExp]"===k(e)&&(e.lastIndex=0,e.test(t))}function oo(e,t){io(e,"a",t)}function so(e,t){io(e,"da",t)}function io(e,t,n=nc){const r=e.__wdc||(e.__wdc=()=>{let t=n;for(;t;){if(t.isDeactivated)return;t=t.parent}return e()});if(uo(t,r,n),n){let e=n.parent;for(;e&&e.parent;)to(e.parent.vnode)&&co(r,t,n,e),e=e.parent}}function co(e,t,n,r){const o=uo(t,e,r,!0);yo(()=>{d(r[t],o)},n)}function lo(e){e.shapeFlag&=-257,e.shapeFlag&=-513}function ao(e){return 128&e.shapeFlag?e.ssContent:e}function uo(e,t,n=nc,r=!1){if(n){const o=n[e]||(n[e]=[]),s=t.__weh||(t.__weh=(...r)=>{He();const o=ic(n),s=An(t,n,e,r);return o(),je(),s});return r?o.unshift(s):o.push(s),s}}const fo=e=>(t,n=nc)=>{fc&&"sp"!==e||uo(e,(...e)=>t(...e),n)},po=fo("bm"),ho=fo("m"),mo=fo("bu"),go=fo("u"),vo=fo("bum"),yo=fo("um"),_o=fo("sp"),bo=fo("rtg"),So=fo("rtc");function xo(e,t=nc){uo("ec",e,t)}const Co="components",To="directives";function ko(e,t){return No(Co,e,!0,t)||e}const Eo=Symbol.for("v-ndc");function wo(e){return b(e)?No(Co,e,!1)||e:e||Eo}function Ao(e){return No(To,e)}function No(e,t,n=!0,r=!1){const o=Jn||nc;if(o){const n=o.type;if(e===Co){const e=xc(n,!1);if(e&&(e===t||e===M(t)||e===L(M(t))))return n}const s=Io(o[e]||n[e],t)||Io(o.appContext[e],t);return!s&&r?n:s}}function Io(e,t){return e&&(e[t]||e[M(t)]||e[L(M(t))])}function Ro(e,t,n,r){let o;const s=n&&n[r],i=m(e);if(i||b(e)){let n=!1,r=!1;i&&Ft(e)&&(n=!Bt(e),r=Vt(e),e=nt(e)),o=new Array(e.length);for(let i=0,c=e.length;it(e,n,void 0,s&&s[n]));else{const n=Object.keys(e);o=new Array(n.length);for(let r=0,i=n.length;r{const t=r.fn(...e);return t&&(t.key=r.key),t}:r.fn)}return e}function Mo(e,t,n={},r,o){if(Jn.ce||Jn.parent&&Qr(Jn.parent)&&Jn.parent.ce)return"default"!==t&&(n.name=t),wi(),Pi(Si,null,[Ui("slot",n,r&&r())],64);let s=e[t];s&&s._c&&(s._d=!1),wi();const i=s&&Po(s(n)),c=n.key||i&&i.key,l=Pi(Si,{key:(c&&!S(c)?c:`_${t}`)+(!i&&r?"_fb":"")},i||(r?r():[]),i&&1===e._?64:-2);return!o&&l.scopeId&&(l.slotScopeIds=[l.scopeId+"-s"]),s&&s._c&&(s._d=!0),l}function Po(e){return e.some(e=>!Di(e)||e.type!==Ci&&!(e.type===Si&&!Po(e.children)))?e:null}function Do(e,t){const n={};for(const r in e)n[t&&/[A-Z]/.test(r)?`on:${r}`:$(r)]=e[r];return n}const Lo=e=>e?lc(e)?_c(e):Lo(e.parent):null,$o=f(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>Lo(e.parent),$root:e=>Lo(e.root),$host:e=>e.ce,$emit:e=>e.emit,$options:e=>is(e),$forceUpdate:e=>e.f||(e.f=()=>{Fn(e.update)}),$nextTick:e=>e.n||(e.n=$n.bind(e.proxy)),$watch:e=>ei.bind(e)}),Fo=(e,t)=>e!==s&&!e.__isScriptSetup&&h(e,t),Vo={get({_:e},t){if("__v_skip"===t)return!0;const{ctx:n,setupState:r,data:o,props:i,accessCache:c,type:l,appContext:a}=e;let u;if("$"!==t[0]){const l=c[t];if(void 0!==l)switch(l){case 1:return r[t];case 2:return o[t];case 4:return n[t];case 3:return i[t]}else{if(Fo(r,t))return c[t]=1,r[t];if(o!==s&&h(o,t))return c[t]=2,o[t];if((u=e.propsOptions[0])&&h(u,t))return c[t]=3,i[t];if(n!==s&&h(n,t))return c[t]=4,n[t];ns&&(c[t]=0)}}const f=$o[t];let d,p;return f?("$attrs"===t&&Ze(e.attrs,0,""),f(e)):(d=l.__cssModules)&&(d=d[t])?d:n!==s&&h(n,t)?(c[t]=4,n[t]):(p=a.config.globalProperties,h(p,t)?p[t]:void 0)},set({_:e},t,n){const{data:r,setupState:o,ctx:i}=e;return Fo(o,t)?(o[t]=n,!0):r!==s&&h(r,t)?(r[t]=n,!0):!h(e.props,t)&&(("$"!==t[0]||!(t.slice(1)in e))&&(i[t]=n,!0))},has({_:{data:e,setupState:t,accessCache:n,ctx:r,appContext:o,propsOptions:i}},c){let l;return!!n[c]||e!==s&&h(e,c)||Fo(t,c)||(l=i[0])&&h(l,c)||h(r,c)||h($o,c)||h(o.config.globalProperties,c)},defineProperty(e,t,n){return null!=n.get?e._.accessCache[t]=0:h(n,"value")&&this.set(e,t,n.value,null),Reflect.defineProperty(e,t,n)}};const Bo=f({},Vo,{get(e,t){if(t!==Symbol.unscopables)return Vo.get(e,t,e)},has(e,t){return"_"!==t[0]&&!W(t)}});function Uo(){return null}function Ho(){return null}function jo(e){0}function qo(e){0}function Wo(){return null}function zo(){0}function Ko(e,t){return null}function Jo(){return Go("useSlots").slots}function Yo(){return Go("useAttrs").attrs}function Go(e){const t=rc();return t.setupContext||(t.setupContext=yc(t))}function Xo(e){return m(e)?e.reduce((e,t)=>(e[t]=null,e),{}):e}function Qo(e,t){const n=Xo(e);for(const e in t){if(e.startsWith("__skip"))continue;let r=n[e];r?m(r)||_(r)?r=n[e]={type:r,default:t[e]}:r.default=t[e]:null===r&&(r=n[e]={default:t[e]}),r&&t[`__skip_${e}`]&&(r.skipFactory=!0)}return n}function Zo(e,t){return e&&t?m(e)&&m(t)?e.concat(t):f({},Xo(e),Xo(t)):e||t}function es(e,t){const n={};for(const r in e)t.includes(r)||Object.defineProperty(n,r,{enumerable:!0,get:()=>e[r]});return n}function ts(e){const t=rc();let n=e();return cc(),C(n)&&(n=n.catch(e=>{throw ic(t),e})),[n,()=>ic(t)]}let ns=!0;function rs(e){const t=is(e),n=e.proxy,r=e.ctx;ns=!1,t.beforeCreate&&os(t.beforeCreate,e,"bc");const{data:o,computed:s,methods:i,watch:l,provide:a,inject:u,created:f,beforeMount:d,mounted:p,beforeUpdate:h,updated:g,activated:v,deactivated:y,beforeDestroy:b,beforeUnmount:S,destroyed:C,unmounted:T,render:k,renderTracked:E,renderTriggered:w,errorCaptured:A,serverPrefetch:N,expose:I,inheritAttrs:R,components:O,directives:M,filters:P}=t;if(u&&function(e,t){m(e)&&(e=us(e));for(const n in e){const r=e[n];let o;o=x(r)?"default"in r?_s(r.from||n,r.default,!0):_s(r.from||n):_s(r),zt(o)?Object.defineProperty(t,n,{enumerable:!0,configurable:!0,get:()=>o.value,set:e=>o.value=e}):t[n]=o}}(u,r,null),i)for(const e in i){const t=i[e];_(t)&&(r[e]=t.bind(n))}if(o){0;const t=o.call(n,n);0,x(t)&&(e.data=Mt(t))}if(ns=!0,s)for(const e in s){const t=s[e],o=_(t)?t.bind(n,n):_(t.get)?t.get.bind(n,n):c;0;const i=!_(t)&&_(t.set)?t.set.bind(n):c,l=kc({get:o,set:i});Object.defineProperty(r,e,{enumerable:!0,configurable:!0,get:()=>l.value,set:e=>l.value=e})}if(l)for(const e in l)ss(l[e],r,n,e);if(a){const e=_(a)?a.call(n):a;Reflect.ownKeys(e).forEach(t=>{ys(t,e[t])})}function D(e,t){m(t)?t.forEach(t=>e(t.bind(n))):t&&e(t.bind(n))}if(f&&os(f,e,"c"),D(po,d),D(ho,p),D(mo,h),D(go,g),D(oo,v),D(so,y),D(xo,A),D(So,E),D(bo,w),D(vo,S),D(yo,T),D(_o,N),m(I))if(I.length){const t=e.exposed||(e.exposed={});I.forEach(e=>{Object.defineProperty(t,e,{get:()=>n[e],set:t=>n[e]=t,enumerable:!0})})}else e.exposed||(e.exposed={});k&&e.render===c&&(e.render=k),null!=R&&(e.inheritAttrs=R),O&&(e.components=O),M&&(e.directives=M),N&&Rr(e)}function os(e,t,n){An(m(e)?e.map(e=>e.bind(t.proxy)):e.bind(t.proxy),t,n)}function ss(e,t,n,r){let o=r.includes(".")?ti(n,r):()=>n[r];if(b(e)){const n=t[e];_(n)&&Qs(o,n)}else if(_(e))Qs(o,e.bind(n));else if(x(e))if(m(e))e.forEach(e=>ss(e,t,n,r));else{const r=_(e.handler)?e.handler.bind(n):t[e.handler];_(r)&&Qs(o,r,e)}else 0}function is(e){const t=e.type,{mixins:n,extends:r}=t,{mixins:o,optionsCache:s,config:{optionMergeStrategies:i}}=e.appContext,c=s.get(t);let l;return c?l=c:o.length||n||r?(l={},o.length&&o.forEach(e=>cs(l,e,i,!0)),cs(l,t,i)):l=t,x(t)&&s.set(t,l),l}function cs(e,t,n,r=!1){const{mixins:o,extends:s}=t;s&&cs(e,s,n,!0),o&&o.forEach(t=>cs(e,t,n,!0));for(const o in t)if(r&&"expose"===o);else{const r=ls[o]||n&&n[o];e[o]=r?r(e[o],t[o]):t[o]}return e}const ls={data:as,props:ps,emits:ps,methods:ds,computed:ds,beforeCreate:fs,created:fs,beforeMount:fs,mounted:fs,beforeUpdate:fs,updated:fs,beforeDestroy:fs,beforeUnmount:fs,destroyed:fs,unmounted:fs,activated:fs,deactivated:fs,errorCaptured:fs,serverPrefetch:fs,components:ds,directives:ds,watch:function(e,t){if(!e)return t;if(!t)return e;const n=f(Object.create(null),e);for(const r in t)n[r]=fs(e[r],t[r]);return n},provide:as,inject:function(e,t){return ds(us(e),us(t))}};function as(e,t){return t?e?function(){return f(_(e)?e.call(this,this):e,_(t)?t.call(this,this):t)}:t:e}function us(e){if(m(e)){const t={};for(let n=0;n1)return n&&_(t)?t.call(r&&r.proxy):t}else 0}function bs(){return!(!rc()&&!vs)}const Ss={},xs=()=>Object.create(Ss),Cs=e=>Object.getPrototypeOf(e)===Ss;function Ts(e,t,n,r){const[o,i]=e.propsOptions;let c,l=!1;if(t)for(let s in t){if(N(s))continue;const a=t[s];let u;o&&h(o,u=M(s))?i&&i.includes(u)?(c||(c={}))[u]=a:n[u]=a:ii(e.emitsOptions,s)||s in r&&a===r[s]||(r[s]=a,l=!0)}if(i){const t=Ht(n),r=c||s;for(let s=0;s{u=!0;const[n,r]=ws(e,t,!0);f(l,n),r&&a.push(...r)};!n&&t.mixins.length&&t.mixins.forEach(r),e.extends&&r(e.extends),e.mixins&&e.mixins.forEach(r)}if(!c&&!u)return x(e)&&r.set(e,i),i;if(m(c))for(let e=0;e"_"===e||"__"===e||"_ctx"===e||"$stable"===e,Is=e=>m(e)?e.map(Ji):[Ji(e)],Rs=(e,t,n)=>{if(t._n)return t;const r=er((...e)=>Is(t(...e)),n);return r._c=!1,r},Os=(e,t,n)=>{const r=e._ctx;for(const n in e){if(Ns(n))continue;const o=e[n];if(_(o))t[n]=Rs(0,o,r);else if(null!=o){0;const e=Is(o);t[n]=()=>e}}},Ms=(e,t)=>{const n=Is(t);e.slots.default=()=>n},Ps=(e,t,n)=>{for(const r in t)!n&&Ns(r)||(e[r]=t[r])},Ds=(e,t,n)=>{const r=e.slots=xs();if(32&e.vnode.shapeFlag){const e=t.__;e&&B(r,"__",e,!0);const o=t._;o?(Ps(r,t,n),n&&B(r,"_",o,!0)):Os(t,r)}else t&&Ms(e,t)},Ls=(e,t,n)=>{const{vnode:r,slots:o}=e;let i=!0,c=s;if(32&r.shapeFlag){const e=t._;e?n&&1===e?i=!1:Ps(o,t,n):(i=!t.$stable,Os(t,o)),c=t}else t&&(Ms(e,t),c={default:1});if(i)for(const e in o)Ns(e)||null!=c[e]||delete o[e]};const $s=_i;function Fs(e){return Bs(e)}function Vs(e){return Bs(e,Fr)}function Bs(e,t){"boolean"!=typeof __VUE_PROD_HYDRATION_MISMATCH_DETAILS__&&(q().__VUE_PROD_HYDRATION_MISMATCH_DETAILS__=!1);q().__VUE__=!0;const{insert:n,remove:r,patchProp:o,createElement:l,createText:a,createComment:u,setText:f,setElementText:d,parentNode:p,nextSibling:g,setScopeId:v=c,insertStaticContent:y}=e,_=(e,t,n,r=null,o=null,s=null,i=void 0,c=null,l=!!t.dynamicChildren)=>{if(e===t)return;e&&!Li(e,t)&&(r=X(e),z(e,o,s,!0),e=null),-2===t.patchFlag&&(l=!1,t.dynamicChildren=null);const{type:a,ref:u,shapeFlag:f}=t;switch(a){case xi:b(e,t,n,r);break;case Ci:S(e,t,n,r);break;case Ti:null==e&&x(t,n,r,i);break;case Si:O(e,t,n,r,o,s,i,c,l);break;default:1&f?T(e,t,n,r,o,s,i,c,l):6&f?P(e,t,n,r,o,s,i,c,l):(64&f||128&f)&&a.process(e,t,n,r,o,s,i,c,l,ee)}null!=u&&o?Mr(u,e&&e.ref,s,t||e,!t):null==u&&e&&null!=e.ref&&Mr(e.ref,null,s,e,!0)},b=(e,t,r,o)=>{if(null==e)n(t.el=a(t.children),r,o);else{const n=t.el=e.el;t.children!==e.children&&f(n,t.children)}},S=(e,t,r,o)=>{null==e?n(t.el=u(t.children||""),r,o):t.el=e.el},x=(e,t,n,r)=>{[e.el,e.anchor]=y(e.children,t,n,r,e.el,e.anchor)},C=({el:e,anchor:t})=>{let n;for(;e&&e!==t;)n=g(e),r(e),e=n;r(t)},T=(e,t,n,r,o,s,i,c,l)=>{"svg"===t.type?i="svg":"math"===t.type&&(i="mathml"),null==e?k(t,n,r,o,s,i,c,l):A(e,t,o,s,i,c,l)},k=(e,t,r,s,i,c,a,u)=>{let f,p;const{props:h,shapeFlag:m,transition:g,dirs:v}=e;if(f=e.el=l(e.type,c,h&&h.is,h),8&m?d(f,e.children):16&m&&w(e.children,f,null,s,i,Us(e,c),a,u),v&&nr(e,null,s,"created"),E(f,e,e.scopeId,a,s),h){for(const e in h)"value"===e||N(e)||o(f,e,null,h[e],c,s);"value"in h&&o(f,"value",null,h.value,c),(p=h.onVnodeBeforeMount)&&Qi(p,s,e)}v&&nr(e,null,s,"beforeMount");const y=js(i,g);y&&g.beforeEnter(f),n(f,t,r),((p=h&&h.onVnodeMounted)||y||v)&&$s(()=>{p&&Qi(p,s,e),y&&g.enter(f),v&&nr(e,null,s,"mounted")},i)},E=(e,t,n,r,o)=>{if(n&&v(e,n),r)for(let t=0;t{for(let a=l;a{const a=t.el=e.el;let{patchFlag:u,dynamicChildren:f,dirs:p}=t;u|=16&e.patchFlag;const h=e.props||s,m=t.props||s;let g;if(n&&Hs(n,!1),(g=m.onVnodeBeforeUpdate)&&Qi(g,n,t,e),p&&nr(t,e,n,"beforeUpdate"),n&&Hs(n,!0),(h.innerHTML&&null==m.innerHTML||h.textContent&&null==m.textContent)&&d(a,""),f?I(e.dynamicChildren,f,a,n,r,Us(t,i),c):l||U(e,t,a,null,n,r,Us(t,i),c,!1),u>0){if(16&u)R(a,h,m,n,i);else if(2&u&&h.class!==m.class&&o(a,"class",null,m.class,i),4&u&&o(a,"style",h.style,m.style,i),8&u){const e=t.dynamicProps;for(let t=0;t{g&&Qi(g,n,t,e),p&&nr(t,e,n,"updated")},r)},I=(e,t,n,r,o,s,i)=>{for(let c=0;c{if(t!==n){if(t!==s)for(const s in t)N(s)||s in n||o(e,s,t[s],null,i,r);for(const s in n){if(N(s))continue;const c=n[s],l=t[s];c!==l&&"value"!==s&&o(e,s,l,c,i,r)}"value"in n&&o(e,"value",t.value,n.value,i)}},O=(e,t,r,o,s,i,c,l,u)=>{const f=t.el=e?e.el:a(""),d=t.anchor=e?e.anchor:a("");let{patchFlag:p,dynamicChildren:h,slotScopeIds:m}=t;m&&(l=l?l.concat(m):m),null==e?(n(f,r,o),n(d,r,o),w(t.children||[],r,d,s,i,c,l,u)):p>0&&64&p&&h&&e.dynamicChildren?(I(e.dynamicChildren,h,r,s,i,c,l),(null!=t.key||s&&t===s.subTree)&&qs(e,t,!0)):U(e,t,r,d,s,i,c,l,u)},P=(e,t,n,r,o,s,i,c,l)=>{t.slotScopeIds=c,null==e?512&t.shapeFlag?o.ctx.activate(t,n,r,i,l):L(t,n,r,o,s,i,l):$(e,t,l)},L=(e,t,n,r,o,s,i)=>{const c=e.component=tc(e,r,o);if(to(e)&&(c.ctx.renderer=ee),dc(c,!1,i),c.asyncDep){if(o&&o.registerDep(c,F,i),!e.el){const r=c.subTree=Ui(Ci);S(null,r,t,n),e.placeholder=r.el}}else F(c,e,t,n,o,s,i)},$=(e,t,n)=>{const r=t.component=e.component;if(function(e,t,n){const{props:r,children:o,component:s}=e,{props:i,children:c,patchFlag:l}=t,a=s.emitsOptions;0;if(t.dirs||t.transition)return!0;if(!(n&&l>=0))return!(!o&&!c||c&&c.$stable)||r!==i&&(r?!i||fi(r,i,a):!!i);if(1024&l)return!0;if(16&l)return r?fi(r,i,a):!!i;if(8&l){const e=t.dynamicProps;for(let t=0;t{const c=()=>{if(e.isMounted){let{next:t,bu:n,u:r,parent:l,vnode:a}=e;{const n=Ws(e);if(n)return t&&(t.el=a.el,B(e,t,i)),void n.asyncDep.then(()=>{e.isUnmounted||c()})}let u,f=t;0,Hs(e,!1),t?(t.el=a.el,B(e,t,i)):t=a,n&&V(n),(u=t.props&&t.props.onVnodeBeforeUpdate)&&Qi(u,l,t,a),Hs(e,!0);const d=ci(e);0;const h=e.subTree;e.subTree=d,_(h,d,p(h.el),X(h),e,o,s),t.el=d.el,null===f&&di(e,d.el),r&&$s(r,o),(u=t.props&&t.props.onVnodeUpdated)&&$s(()=>Qi(u,l,t,a),o)}else{let i;const{el:c,props:l}=t,{bm:a,m:u,parent:f,root:d,type:p}=e,h=Qr(t);if(Hs(e,!1),a&&V(a),!h&&(i=l&&l.onVnodeBeforeMount)&&Qi(i,f,t),Hs(e,!0),c&&ne){const t=()=>{e.subTree=ci(e),ne(c,e.subTree,e,o,null)};h&&p.__asyncHydrate?p.__asyncHydrate(c,e,t):t()}else{d.ce&&!1!==d.ce._def.shadowRoot&&d.ce._injectChildStyle(p);const i=e.subTree=ci(e);0,_(null,i,n,r,e,o,s),t.el=i.el}if(u&&$s(u,o),!h&&(i=l&&l.onVnodeMounted)){const e=t;$s(()=>Qi(i,f,e),o)}(256&t.shapeFlag||f&&Qr(f.vnode)&&256&f.vnode.shapeFlag)&&e.a&&$s(e.a,o),e.isMounted=!0,t=n=r=null}};e.scope.on();const l=e.effect=new ke(c);e.scope.off();const a=e.update=l.run.bind(l),u=e.job=l.runIfDirty.bind(l);u.i=e,u.id=e.uid,l.scheduler=()=>Fn(u),Hs(e,!0),a()},B=(e,t,n)=>{t.component=e;const r=e.vnode.props;e.vnode=t,e.next=null,function(e,t,n,r){const{props:o,attrs:s,vnode:{patchFlag:i}}=e,c=Ht(o),[l]=e.propsOptions;let a=!1;if(!(r||i>0)||16&i){let r;Ts(e,t,o,s)&&(a=!0);for(const s in c)t&&(h(t,s)||(r=D(s))!==s&&h(t,r))||(l?!n||void 0===n[s]&&void 0===n[r]||(o[s]=ks(l,c,s,void 0,e,!0)):delete o[s]);if(s!==c)for(const e in s)t&&h(t,e)||(delete s[e],a=!0)}else if(8&i){const n=e.vnode.dynamicProps;for(let r=0;r{const a=e&&e.children,u=e?e.shapeFlag:0,f=t.children,{patchFlag:p,shapeFlag:h}=t;if(p>0){if(128&p)return void j(a,f,n,r,o,s,i,c,l);if(256&p)return void H(a,f,n,r,o,s,i,c,l)}8&h?(16&u&&G(a,o,s),f!==a&&d(n,f)):16&u?16&h?j(a,f,n,r,o,s,i,c,l):G(a,o,s,!0):(8&u&&d(n,""),16&h&&w(f,n,r,o,s,i,c,l))},H=(e,t,n,r,o,s,c,l,a)=>{t=t||i;const u=(e=e||i).length,f=t.length,d=Math.min(u,f);let p;for(p=0;pf?G(e,o,s,!0,!1,d):w(t,n,r,o,s,c,l,a,d)},j=(e,t,n,r,o,s,c,l,a)=>{let u=0;const f=t.length;let d=e.length-1,p=f-1;for(;u<=d&&u<=p;){const r=e[u],i=t[u]=a?Yi(t[u]):Ji(t[u]);if(!Li(r,i))break;_(r,i,n,null,o,s,c,l,a),u++}for(;u<=d&&u<=p;){const r=e[d],i=t[p]=a?Yi(t[p]):Ji(t[p]);if(!Li(r,i))break;_(r,i,n,null,o,s,c,l,a),d--,p--}if(u>d){if(u<=p){const e=p+1,i=ep)for(;u<=d;)z(e[u],o,s,!0),u++;else{const h=u,m=u,g=new Map;for(u=m;u<=p;u++){const e=t[u]=a?Yi(t[u]):Ji(t[u]);null!=e.key&&g.set(e.key,u)}let v,y=0;const b=p-m+1;let S=!1,x=0;const C=new Array(b);for(u=0;u=b){z(r,o,s,!0);continue}let i;if(null!=r.key)i=g.get(r.key);else for(v=m;v<=p;v++)if(0===C[v-m]&&Li(r,t[v])){i=v;break}void 0===i?z(r,o,s,!0):(C[i-m]=u+1,i>=x?x=i:S=!0,_(r,t[i],n,null,o,s,c,l,a),y++)}const T=S?function(e){const t=e.slice(),n=[0];let r,o,s,i,c;const l=e.length;for(r=0;r>1,e[n[c]]0&&(t[r]=n[s-1]),n[s]=r)}}s=n.length,i=n[s-1];for(;s-- >0;)n[s]=i,i=t[i];return n}(C):i;for(v=T.length-1,u=b-1;u>=0;u--){const e=m+u,i=t[e],d=t[e+1],p=e+1{const{el:c,type:l,transition:a,children:u,shapeFlag:f}=e;if(6&f)return void W(e.component.subTree,t,o,s);if(128&f)return void e.suspense.move(t,o,s);if(64&f)return void l.move(e,t,o,ee);if(l===Si){n(c,t,o);for(let e=0;e{let s;for(;e&&e!==t;)s=g(e),n(e,r,o),e=s;n(t,r,o)})(e,t,o);if(2!==s&&1&f&&a)if(0===s)a.beforeEnter(c),n(c,t,o),$s(()=>a.enter(c),i);else{const{leave:s,delayLeave:i,afterLeave:l}=a,u=()=>{e.ctx.isUnmounted?r(c):n(c,t,o)},f=()=>{s(c,()=>{u(),l&&l()})};i?i(c,u,f):f()}else n(c,t,o)},z=(e,t,n,r=!1,o=!1)=>{const{type:s,props:i,ref:c,children:l,dynamicChildren:a,shapeFlag:u,patchFlag:f,dirs:d,cacheIndex:p}=e;if(-2===f&&(o=!1),null!=c&&(He(),Mr(c,null,n,e,!0),je()),null!=p&&(t.renderCache[p]=void 0),256&u)return void t.ctx.deactivate(e);const h=1&u&&d,m=!Qr(e);let g;if(m&&(g=i&&i.onVnodeBeforeUnmount)&&Qi(g,t,e),6&u)Y(e.component,n,r);else{if(128&u)return void e.suspense.unmount(n,r);h&&nr(e,null,t,"beforeUnmount"),64&u?e.type.remove(e,t,n,ee,r):a&&!a.hasOnce&&(s!==Si||f>0&&64&f)?G(a,t,n,!1,!0):(s===Si&&384&f||!o&&16&u)&&G(l,t,n),r&&K(e)}(m&&(g=i&&i.onVnodeUnmounted)||h)&&$s(()=>{g&&Qi(g,t,e),h&&nr(e,null,t,"unmounted")},n)},K=e=>{const{type:t,el:n,anchor:o,transition:s}=e;if(t===Si)return void J(n,o);if(t===Ti)return void C(e);const i=()=>{r(n),s&&!s.persisted&&s.afterLeave&&s.afterLeave()};if(1&e.shapeFlag&&s&&!s.persisted){const{leave:t,delayLeave:r}=s,o=()=>t(n,i);r?r(e.el,i,o):o()}else i()},J=(e,t)=>{let n;for(;e!==t;)n=g(e),r(e),e=n;r(t)},Y=(e,t,n)=>{const{bum:r,scope:o,job:s,subTree:i,um:c,m:l,a:a,parent:u,slots:{__:f}}=e;zs(l),zs(a),r&&V(r),u&&m(f)&&f.forEach(e=>{u.renderCache[e]=void 0}),o.stop(),s&&(s.flags|=8,z(i,e,t,n)),c&&$s(c,t),$s(()=>{e.isUnmounted=!0},t),t&&t.pendingBranch&&!t.isUnmounted&&e.asyncDep&&!e.asyncResolved&&e.suspenseId===t.pendingId&&(t.deps--,0===t.deps&&t.resolve())},G=(e,t,n,r=!1,o=!1,s=0)=>{for(let i=s;i{if(6&e.shapeFlag)return X(e.component.subTree);if(128&e.shapeFlag)return e.suspense.next();const t=g(e.anchor||e.el),n=t&&t[rr];return n?g(n):t};let Q=!1;const Z=(e,t,n)=>{null==e?t._vnode&&z(t._vnode,null,null,!0):_(t._vnode||null,e,t,null,null,null,n),t._vnode=e,Q||(Q=!0,Un(),Hn(),Q=!1)},ee={p:_,um:z,m:W,r:K,mt:L,mc:w,pc:U,pbc:I,n:X,o:e};let te,ne;return t&&([te,ne]=t(ee)),{render:Z,hydrate:te,createApp:gs(Z,te)}}function Us({type:e,props:t},n){return"svg"===n&&"foreignObject"===e||"mathml"===n&&"annotation-xml"===e&&t&&t.encoding&&t.encoding.includes("html")?void 0:n}function Hs({effect:e,job:t},n){n?(e.flags|=32,t.flags|=4):(e.flags&=-33,t.flags&=-5)}function js(e,t){return(!e||e&&!e.pendingBranch)&&t&&!t.persisted}function qs(e,t,n=!1){const r=e.children,o=t.children;if(m(r)&&m(o))for(let e=0;e{{const e=_s(Ks);return e}};function Ys(e,t){return Zs(e,null,t)}function Gs(e,t){return Zs(e,null,{flush:"post"})}function Xs(e,t){return Zs(e,null,{flush:"sync"})}function Qs(e,t,n){return Zs(e,t,n)}function Zs(e,t,n=s){const{immediate:r,deep:o,flush:i,once:l}=n;const a=f({},n);const u=t&&r||!t&&"post"!==i;let p;if(fc)if("sync"===i){const e=Js();p=e.__watcherHandles||(e.__watcherHandles=[])}else if(!u){const e=()=>{};return e.stop=c,e.resume=c,e.pause=c,e}const h=nc;a.call=(e,t,n)=>An(e,h,t,n);let g=!1;"post"===i?a.scheduler=e=>{$s(e,h&&h.suspense)}:"sync"!==i&&(g=!0,a.scheduler=(e,t)=>{t?e():Fn(e)}),a.augmentJob=e=>{t&&(e.flags|=4),g&&(e.flags|=2,h&&(e.id=h.uid,e.i=h))};const v=function(e,t,n=s){const{immediate:r,deep:o,once:i,scheduler:l,augmentJob:a,call:u}=n,f=e=>o?e:Bt(e)||!1===o||0===o?yn(e,1):yn(e);let p,h,g,v,y=!1,b=!1;if(zt(e)?(h=()=>e.value,y=Bt(e)):Ft(e)?(h=()=>f(e),y=!0):m(e)?(b=!0,y=e.some(e=>Ft(e)||Bt(e)),h=()=>e.map(e=>zt(e)?e.value:Ft(e)?f(e):_(e)?u?u(e,2):e():void 0)):h=_(e)?t?u?()=>u(e,2):e:()=>{if(g){He();try{g()}finally{je()}}const t=mn;mn=p;try{return u?u(e,3,[v]):e(v)}finally{mn=t}}:c,t&&o){const e=h,t=!0===o?1/0:o;h=()=>yn(e(),t)}const S=xe(),x=()=>{p.stop(),S&&S.active&&d(S.effects,p)};if(i&&t){const e=t;t=(...t)=>{e(...t),x()}}let C=b?new Array(e.length).fill(pn):pn;const T=e=>{if(1&p.flags&&(p.dirty||e))if(t){const e=p.run();if(o||y||(b?e.some((e,t)=>F(e,C[t])):F(e,C))){g&&g();const n=mn;mn=p;try{const n=[e,C===pn?void 0:b&&C[0]===pn?[]:C,v];C=e,u?u(t,3,n):t(...n)}finally{mn=n}}}else p.run()};return a&&a(T),p=new ke(h),p.scheduler=l?()=>l(T,!1):T,v=e=>vn(e,!1,p),g=p.onStop=()=>{const e=hn.get(p);if(e){if(u)u(e,4);else for(const t of e)t();hn.delete(p)}},t?r?T(!0):C=p.run():l?l(T.bind(null,!0),!0):p.run(),x.pause=p.pause.bind(p),x.resume=p.resume.bind(p),x.stop=x,x}(e,t,a);return fc&&(p?p.push(v):u&&v()),v}function ei(e,t,n){const r=this.proxy,o=b(e)?e.includes(".")?ti(r,e):()=>r[e]:e.bind(r,r);let s;_(t)?s=t:(s=t.handler,n=t);const i=ic(this),c=Zs(o,s.bind(r),n);return i(),c}function ti(e,t){const n=t.split(".");return()=>{let t=e;for(let e=0;e{let a,u,f=s;return Xs(()=>{const t=e[o];F(a,t)&&(a=t,l())}),{get(){return c(),n.get?n.get(a):a},set(e){const c=n.set?n.set(e):e;if(!(F(c,a)||f!==s&&F(e,f)))return;const d=r.vnode.props;d&&(t in d||o in d||i in d)&&(`onUpdate:${t}`in d||`onUpdate:${o}`in d||`onUpdate:${i}`in d)||(a=e,l()),r.emit(`update:${t}`,c),F(e,c)&&F(e,f)&&!F(c,u)&&l(),f=e,u=c}}});return l[Symbol.iterator]=()=>{let e=0;return{next(){return e<2?{value:e++?c||s:l,done:!1}:{done:!0}}}},l}const ri=(e,t)=>"modelValue"===t||"model-value"===t?e.modelModifiers:e[`${t}Modifiers`]||e[`${M(t)}Modifiers`]||e[`${D(t)}Modifiers`];function oi(e,t,...n){if(e.isUnmounted)return;const r=e.vnode.props||s;let o=n;const i=t.startsWith("update:"),c=i&&ri(r,t.slice(7));let l;c&&(c.trim&&(o=n.map(e=>b(e)?e.trim():e)),c.number&&(o=n.map(U)));let a=r[l=$(t)]||r[l=$(M(t))];!a&&i&&(a=r[l=$(D(t))]),a&&An(a,e,6,o);const u=r[l+"Once"];if(u){if(e.emitted){if(e.emitted[l])return}else e.emitted={};e.emitted[l]=!0,An(u,e,6,o)}}function si(e,t,n=!1){const r=t.emitsCache,o=r.get(e);if(void 0!==o)return o;const s=e.emits;let i={},c=!1;if(!_(e)){const r=e=>{const n=si(e,t,!0);n&&(c=!0,f(i,n))};!n&&t.mixins.length&&t.mixins.forEach(r),e.extends&&r(e.extends),e.mixins&&e.mixins.forEach(r)}return s||c?(m(s)?s.forEach(e=>i[e]=null):f(i,s),x(e)&&r.set(e,i),i):(x(e)&&r.set(e,null),null)}function ii(e,t){return!(!e||!a(t))&&(t=t.slice(2).replace(/Once$/,""),h(e,t[0].toLowerCase()+t.slice(1))||h(e,D(t))||h(e,t))}function ci(e){const{type:t,vnode:n,proxy:r,withProxy:o,propsOptions:[s],slots:i,attrs:c,emit:l,render:a,renderCache:f,props:d,data:p,setupState:h,ctx:m,inheritAttrs:g}=e,v=Gn(e);let y,_;try{if(4&n.shapeFlag){const e=o||r,t=e;y=Ji(a.call(t,e,f,d,h,p,m)),_=c}else{const e=t;0,y=Ji(e.length>1?e(d,{attrs:c,slots:i,emit:l}):e(d,null)),_=t.props?c:ai(c)}}catch(t){ki.length=0,Nn(t,e,1),y=Ui(Ci)}let b=y;if(_&&!1!==g){const e=Object.keys(_),{shapeFlag:t}=b;e.length&&7&t&&(s&&e.some(u)&&(_=ui(_,s)),b=qi(b,_,!1,!0))}return n.dirs&&(b=qi(b,null,!1,!0),b.dirs=b.dirs?b.dirs.concat(n.dirs):n.dirs),n.transition&&wr(b,n.transition),y=b,Gn(v),y}function li(e,t=!0){let n;for(let t=0;t{let t;for(const n in e)("class"===n||"style"===n||a(n))&&((t||(t={}))[n]=e[n]);return t},ui=(e,t)=>{const n={};for(const r in e)u(r)&&r.slice(9)in t||(n[r]=e[r]);return n};function fi(e,t,n){const r=Object.keys(t);if(r.length!==Object.keys(e).length)return!0;for(let o=0;oe.__isSuspense;let hi=0;const mi={name:"Suspense",__isSuspense:!0,process(e,t,n,r,o,s,i,c,l,a){if(null==e)!function(e,t,n,r,o,s,i,c,l){const{p:a,o:{createElement:u}}=l,f=u("div"),d=e.suspense=vi(e,o,r,t,f,n,s,i,c,l);a(null,d.pendingBranch=e.ssContent,f,null,r,d,s,i),d.deps>0?(gi(e,"onPending"),gi(e,"onFallback"),a(null,e.ssFallback,t,n,r,null,s,i),bi(d,e.ssFallback)):d.resolve(!1,!0)}(t,n,r,o,s,i,c,l,a);else{if(s&&s.deps>0&&!e.suspense.isInFallback)return t.suspense=e.suspense,t.suspense.vnode=t,void(t.el=e.el);!function(e,t,n,r,o,s,i,c,{p:l,um:a,o:{createElement:u}}){const f=t.suspense=e.suspense;f.vnode=t,t.el=e.el;const d=t.ssContent,p=t.ssFallback,{activeBranch:h,pendingBranch:m,isInFallback:g,isHydrating:v}=f;if(m)f.pendingBranch=d,Li(d,m)?(l(m,d,f.hiddenContainer,null,o,f,s,i,c),f.deps<=0?f.resolve():g&&(v||(l(h,p,n,r,o,null,s,i,c),bi(f,p)))):(f.pendingId=hi++,v?(f.isHydrating=!1,f.activeBranch=m):a(m,o,f),f.deps=0,f.effects.length=0,f.hiddenContainer=u("div"),g?(l(null,d,f.hiddenContainer,null,o,f,s,i,c),f.deps<=0?f.resolve():(l(h,p,n,r,o,null,s,i,c),bi(f,p))):h&&Li(d,h)?(l(h,d,n,r,o,f,s,i,c),f.resolve(!0)):(l(null,d,f.hiddenContainer,null,o,f,s,i,c),f.deps<=0&&f.resolve()));else if(h&&Li(d,h))l(h,d,n,r,o,f,s,i,c),bi(f,d);else if(gi(t,"onPending"),f.pendingBranch=d,512&d.shapeFlag?f.pendingId=d.component.suspenseId:f.pendingId=hi++,l(null,d,f.hiddenContainer,null,o,f,s,i,c),f.deps<=0)f.resolve();else{const{timeout:e,pendingId:t}=f;e>0?setTimeout(()=>{f.pendingId===t&&f.fallback(p)},e):0===e&&f.fallback(p)}}(e,t,n,r,o,i,c,l,a)}},hydrate:function(e,t,n,r,o,s,i,c,l){const a=t.suspense=vi(t,r,n,e.parentNode,document.createElement("div"),null,o,s,i,c,!0),u=l(e,a.pendingBranch=t.ssContent,n,a,s,i);0===a.deps&&a.resolve(!1,!0);return u},normalize:function(e){const{shapeFlag:t,children:n}=e,r=32&t;e.ssContent=yi(r?n.default:n),e.ssFallback=r?yi(n.fallback):Ui(Ci)}};function gi(e,t){const n=e.props&&e.props[t];_(n)&&n()}function vi(e,t,n,r,o,s,i,c,l,a,u=!1){const{p:f,m:d,um:p,n:h,o:{parentNode:m,remove:g}}=a;let v;const y=function(e){const t=e.props&&e.props.suspensible;return null!=t&&!1!==t}(e);y&&t&&t.pendingBranch&&(v=t.pendingId,t.deps++);const _=e.props?H(e.props.timeout):void 0;const b=s,S={vnode:e,parent:t,parentComponent:n,namespace:i,container:r,hiddenContainer:o,deps:0,pendingId:hi++,timeout:"number"==typeof _?_:-1,activeBranch:null,pendingBranch:null,isInFallback:!u,isHydrating:u,isUnmounted:!1,effects:[],resolve(e=!1,n=!1){const{vnode:r,activeBranch:o,pendingBranch:i,pendingId:c,effects:l,parentComponent:a,container:u}=S;let f=!1;S.isHydrating?S.isHydrating=!1:e||(f=o&&i.transition&&"out-in"===i.transition.mode,f&&(o.transition.afterLeave=()=>{c===S.pendingId&&(d(i,u,s===b?h(o):s,0),Bn(l))}),o&&(m(o.el)===u&&(s=h(o)),p(o,a,S,!0)),f||d(i,u,s,0)),bi(S,i),S.pendingBranch=null,S.isInFallback=!1;let g=S.parent,_=!1;for(;g;){if(g.pendingBranch){g.effects.push(...l),_=!0;break}g=g.parent}_||f||Bn(l),S.effects=[],y&&t&&t.pendingBranch&&v===t.pendingId&&(t.deps--,0!==t.deps||n||t.resolve()),gi(r,"onResolve")},fallback(e){if(!S.pendingBranch)return;const{vnode:t,activeBranch:n,parentComponent:r,container:o,namespace:s}=S;gi(t,"onFallback");const i=h(n),a=()=>{S.isInFallback&&(f(null,e,o,i,r,null,s,c,l),bi(S,e))},u=e.transition&&"out-in"===e.transition.mode;u&&(n.transition.afterLeave=a),S.isInFallback=!0,p(n,r,null,!0),u||a()},move(e,t,n){S.activeBranch&&d(S.activeBranch,e,t,n),S.container=e},next(){return S.activeBranch&&h(S.activeBranch)},registerDep(e,t,n){const r=!!S.pendingBranch;r&&S.deps++;const o=e.vnode.el;e.asyncDep.catch(t=>{Nn(t,e,0)}).then(s=>{if(e.isUnmounted||S.isUnmounted||S.pendingId!==e.suspenseId)return;e.asyncResolved=!0;const{vnode:c}=e;pc(e,s,!1),o&&(c.el=o);const l=!o&&e.subTree.el;t(e,c,m(o||e.subTree.el),o?null:h(e.subTree),S,i,n),l&&g(l),di(e,c.el),r&&0===--S.deps&&S.resolve()})},unmount(e,t){S.isUnmounted=!0,S.activeBranch&&p(S.activeBranch,n,e,t),S.pendingBranch&&p(S.pendingBranch,n,e,t)}};return S}function yi(e){let t;if(_(e)){const n=Ii&&e._c;n&&(e._d=!1,wi()),e=e(),n&&(e._d=!0,t=Ei,Ai())}if(m(e)){const t=li(e);0,e=t}return e=Ji(e),t&&!e.dynamicChildren&&(e.dynamicChildren=t.filter(t=>t!==e)),e}function _i(e,t){t&&t.pendingBranch?m(e)?t.effects.push(...e):t.effects.push(e):Bn(e)}function bi(e,t){e.activeBranch=t;const{vnode:n,parentComponent:r}=e;let o=t.el;for(;!o&&t.component;)o=(t=t.component.subTree).el;n.el=o,r&&r.subTree===n&&(r.vnode.el=o,di(r,o))}const Si=Symbol.for("v-fgt"),xi=Symbol.for("v-txt"),Ci=Symbol.for("v-cmt"),Ti=Symbol.for("v-stc"),ki=[];let Ei=null;function wi(e=!1){ki.push(Ei=e?null:[])}function Ai(){ki.pop(),Ei=ki[ki.length-1]||null}let Ni,Ii=1;function Ri(e,t=!1){Ii+=e,e<0&&Ei&&t&&(Ei.hasOnce=!0)}function Oi(e){return e.dynamicChildren=Ii>0?Ei||i:null,Ai(),Ii>0&&Ei&&Ei.push(e),e}function Mi(e,t,n,r,o,s){return Oi(Bi(e,t,n,r,o,s,!0))}function Pi(e,t,n,r,o){return Oi(Ui(e,t,n,r,o,!0))}function Di(e){return!!e&&!0===e.__v_isVNode}function Li(e,t){return e.type===t.type&&e.key===t.key}function $i(e){Ni=e}const Fi=({key:e})=>null!=e?e:null,Vi=({ref:e,ref_key:t,ref_for:n})=>("number"==typeof e&&(e=""+e),null!=e?b(e)||zt(e)||_(e)?{i:Jn,r:e,k:t,f:!!n}:e:null);function Bi(e,t=null,n=null,r=0,o=null,s=(e===Si?0:1),i=!1,c=!1){const l={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&Fi(t),ref:t&&Vi(t),scopeId:Yn,slotScopeIds:null,children:n,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetStart:null,targetAnchor:null,staticCount:0,shapeFlag:s,patchFlag:r,dynamicProps:o,dynamicChildren:null,appContext:null,ctx:Jn};return c?(Gi(l,n),128&s&&e.normalize(l)):n&&(l.shapeFlag|=b(n)?8:16),Ii>0&&!i&&Ei&&(l.patchFlag>0||6&s)&&32!==l.patchFlag&&Ei.push(l),l}const Ui=Hi;function Hi(e,t=null,n=null,r=0,o=null,s=!1){if(e&&e!==Eo||(e=Ci),Di(e)){const r=qi(e,t,!0);return n&&Gi(r,n),Ii>0&&!s&&Ei&&(6&r.shapeFlag?Ei[Ei.indexOf(e)]=r:Ei.push(r)),r.patchFlag=-2,r}if(Tc(e)&&(e=e.__vccOpts),t){t=ji(t);let{class:e,style:n}=t;e&&!b(e)&&(t.class=X(e)),x(n)&&(Ut(n)&&!m(n)&&(n=f({},n)),t.style=z(n))}return Bi(e,t,n,r,o,b(e)?1:pi(e)?128:or(e)?64:x(e)?4:_(e)?2:0,s,!0)}function ji(e){return e?Ut(e)||Cs(e)?f({},e):e:null}function qi(e,t,n=!1,r=!1){const{props:o,ref:s,patchFlag:i,children:c,transition:l}=e,a=t?Xi(o||{},t):o,u={__v_isVNode:!0,__v_skip:!0,type:e.type,props:a,key:a&&Fi(a),ref:t&&t.ref?n&&s?m(s)?s.concat(Vi(t)):[s,Vi(t)]:Vi(t):s,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:c,target:e.target,targetStart:e.targetStart,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Si?-1===i?16:16|i:i,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:l,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&qi(e.ssContent),ssFallback:e.ssFallback&&qi(e.ssFallback),placeholder:e.placeholder,el:e.el,anchor:e.anchor,ctx:e.ctx,ce:e.ce};return l&&r&&wr(u,l.clone(u)),u}function Wi(e=" ",t=0){return Ui(xi,null,e,t)}function zi(e,t){const n=Ui(Ti,null,e);return n.staticCount=t,n}function Ki(e="",t=!1){return t?(wi(),Pi(Ci,null,e)):Ui(Ci,null,e)}function Ji(e){return null==e||"boolean"==typeof e?Ui(Ci):m(e)?Ui(Si,null,e.slice()):Di(e)?Yi(e):Ui(xi,null,String(e))}function Yi(e){return null===e.el&&-1!==e.patchFlag||e.memo?e:qi(e)}function Gi(e,t){let n=0;const{shapeFlag:r}=e;if(null==t)t=null;else if(m(t))n=16;else if("object"==typeof t){if(65&r){const n=t.default;return void(n&&(n._c&&(n._d=!1),Gi(e,n()),n._c&&(n._d=!0)))}{n=32;const r=t._;r||Cs(t)?3===r&&Jn&&(1===Jn.slots._?t._=1:(t._=2,e.patchFlag|=1024)):t._ctx=Jn}}else _(t)?(t={default:t,_ctx:Jn},n=32):(t=String(t),64&r?(n=16,t=[Wi(t)]):n=8);e.children=t,e.shapeFlag|=n}function Xi(...e){const t={};for(let n=0;nnc||Jn;let oc,sc;{const e=q(),t=(t,n)=>{let r;return(r=e[t])||(r=e[t]=[]),r.push(n),e=>{r.length>1?r.forEach(t=>t(e)):r[0](e)}};oc=t("__VUE_INSTANCE_SETTERS__",e=>nc=e),sc=t("__VUE_SSR_SETTERS__",e=>fc=e)}const ic=e=>{const t=nc;return oc(e),e.scope.on(),()=>{e.scope.off(),oc(t)}},cc=()=>{nc&&nc.scope.off(),oc(null)};function lc(e){return 4&e.vnode.shapeFlag}let ac,uc,fc=!1;function dc(e,t=!1,n=!1){t&&sc(t);const{props:r,children:o}=e.vnode,s=lc(e);!function(e,t,n,r=!1){const o={},s=xs();e.propsDefaults=Object.create(null),Ts(e,t,o,s);for(const t in e.propsOptions[0])t in o||(o[t]=void 0);n?e.props=r?o:Pt(o):e.type.props?e.props=o:e.props=s,e.attrs=s}(e,r,s,t),Ds(e,o,n||t);const i=s?function(e,t){const n=e.type;0;e.accessCache=Object.create(null),e.proxy=new Proxy(e.ctx,Vo),!1;const{setup:r}=n;if(r){He();const n=e.setupContext=r.length>1?yc(e):null,o=ic(e),s=wn(r,e,0,[e.props,n]),i=C(s);if(je(),o(),!i&&!e.sp||Qr(e)||Rr(e),i){if(s.then(cc,cc),t)return s.then(n=>{pc(e,n,t)}).catch(t=>{Nn(t,e,0)});e.asyncDep=s}else pc(e,s,t)}else gc(e,t)}(e,t):void 0;return t&&sc(!1),i}function pc(e,t,n){_(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:x(t)&&(e.setupState=tn(t)),gc(e,n)}function hc(e){ac=e,uc=e=>{e.render._rc&&(e.withProxy=new Proxy(e.ctx,Bo))}}const mc=()=>!ac;function gc(e,t,n){const r=e.type;if(!e.render){if(!t&&ac&&!r.render){const t=r.template||is(e).template;if(t){0;const{isCustomElement:n,compilerOptions:o}=e.appContext.config,{delimiters:s,compilerOptions:i}=r,c=f(f({isCustomElement:n,delimiters:s},o),i);r.render=ac(t,c)}}e.render=r.render||c,uc&&uc(e)}{const t=ic(e);He();try{rs(e)}finally{je(),t()}}}const vc={get(e,t){return Ze(e,0,""),e[t]}};function yc(e){const t=t=>{e.exposed=t||{}};return{attrs:new Proxy(e.attrs,vc),slots:e.slots,emit:e.emit,expose:t}}function _c(e){return e.exposed?e.exposeProxy||(e.exposeProxy=new Proxy(tn(jt(e.exposed)),{get(t,n){return n in t?t[n]:n in $o?$o[n](e):void 0},has(e,t){return t in e||t in $o}})):e.proxy}const bc=/(?:^|[-_])(\w)/g,Sc=e=>e.replace(bc,e=>e.toUpperCase()).replace(/[-_]/g,"");function xc(e,t=!0){return _(e)?e.displayName||e.name:e.name||t&&e.__name}function Cc(e,t,n=!1){let r=xc(t);if(!r&&t.__file){const e=t.__file.match(/([^/\\]+)\.\w+$/);e&&(r=e[1])}if(!r&&e&&e.parent){const n=e=>{for(const n in e)if(e[n]===t)return n};r=n(e.components||e.parent.type.components)||n(e.appContext.components)}return r?Sc(r):n?"App":"Anonymous"}function Tc(e){return _(e)&&"__vccOpts"in e}const kc=(e,t)=>{const n=function(e,t,n=!1){let r,o;return _(e)?r=e:(r=e.get,o=e.set),new un(r,o,n)}(e,0,fc);return n};function Ec(e,t,n){const r=arguments.length;return 2===r?x(t)&&!m(t)?Di(t)?Ui(e,null,[t]):Ui(e,t):Ui(e,null,t):(r>3?n=Array.prototype.slice.call(arguments,2):3===r&&Di(n)&&(n=[n]),Ui(e,t,n))}function wc(){return void 0}function Ac(e,t,n,r){const o=n[r];if(o&&Nc(o,e))return o;const s=t();return s.memo=e.slice(),s.cacheIndex=r,n[r]=s}function Nc(e,t){const n=e.memo;if(n.length!=t.length)return!1;for(let e=0;e0&&Ei&&Ei.push(e),!0}const Ic="3.5.18",Rc=c,Oc=En,Mc=Wn,Pc=function e(t,n){var r,o;if(Wn=t,Wn)Wn.enabled=!0,zn.forEach(({event:e,args:t})=>Wn.emit(e,...t)),zn=[];else if("undefined"!=typeof window&&window.HTMLElement&&!(null==(o=null==(r=window.navigator)?void 0:r.userAgent)?void 0:o.includes("jsdom"))){(n.__VUE_DEVTOOLS_HOOK_REPLAY__=n.__VUE_DEVTOOLS_HOOK_REPLAY__||[]).push(t=>{e(t,n)}),setTimeout(()=>{Wn||(n.__VUE_DEVTOOLS_HOOK_REPLAY__=null,Kn=!0,zn=[])},3e3)}else Kn=!0,zn=[]},Dc={createComponentInstance:tc,setupComponent:dc,renderComponentRoot:ci,setCurrentRenderingInstance:Gn,isVNode:Di,normalizeVNode:Ji,getComponentPublicInstance:_c,ensureValidVNode:Po,pushWarningContext:function(e){_n.push(e)},popWarningContext:function(){_n.pop()}},Lc=null,$c=null,Fc=null; +/** +* @vue/runtime-dom v3.5.18 +* (c) 2018-present Yuxi (Evan) You and Vue contributors +* @license MIT +**/ +let Vc;const Bc="undefined"!=typeof window&&window.trustedTypes;if(Bc)try{Vc=Bc.createPolicy("vue",{createHTML:e=>e})}catch(e){}const Uc=Vc?e=>Vc.createHTML(e):e=>e,Hc="undefined"!=typeof document?document:null,jc=Hc&&Hc.createElement("template"),qc={insert:(e,t,n)=>{t.insertBefore(e,n||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,n,r)=>{const o="svg"===t?Hc.createElementNS("http://www.w3.org/2000/svg",e):"mathml"===t?Hc.createElementNS("http://www.w3.org/1998/Math/MathML",e):n?Hc.createElement(e,{is:n}):Hc.createElement(e);return"select"===e&&r&&null!=r.multiple&&o.setAttribute("multiple",r.multiple),o},createText:e=>Hc.createTextNode(e),createComment:e=>Hc.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Hc.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},insertStaticContent(e,t,n,r,o,s){const i=n?n.previousSibling:t.lastChild;if(o&&(o===s||o.nextSibling))for(;t.insertBefore(o.cloneNode(!0),n),o!==s&&(o=o.nextSibling););else{jc.innerHTML=Uc("svg"===r?`${e}`:"mathml"===r?`${e}`:e);const o=jc.content;if("svg"===r||"mathml"===r){const e=o.firstChild;for(;e.firstChild;)o.appendChild(e.firstChild);o.removeChild(e)}t.insertBefore(o,n)}return[i?i.nextSibling:t.firstChild,n?n.previousSibling:t.lastChild]}},Wc="transition",zc="animation",Kc=Symbol("_vtc"),Jc={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String},Yc=f({},_r,Jc),Gc=(e=>(e.displayName="Transition",e.props=Yc,e))((e,{slots:t})=>Ec(xr,Zc(e),t)),Xc=(e,t=[])=>{m(e)?e.forEach(e=>e(...t)):e&&e(...t)},Qc=e=>!!e&&(m(e)?e.some(e=>e.length>1):e.length>1);function Zc(e){const t={};for(const n in e)n in Jc||(t[n]=e[n]);if(!1===e.css)return t;const{name:n="v",type:r,duration:o,enterFromClass:s=`${n}-enter-from`,enterActiveClass:i=`${n}-enter-active`,enterToClass:c=`${n}-enter-to`,appearFromClass:l=s,appearActiveClass:a=i,appearToClass:u=c,leaveFromClass:d=`${n}-leave-from`,leaveActiveClass:p=`${n}-leave-active`,leaveToClass:h=`${n}-leave-to`}=e,m=function(e){if(null==e)return null;if(x(e))return[el(e.enter),el(e.leave)];{const t=el(e);return[t,t]}}(o),g=m&&m[0],v=m&&m[1],{onBeforeEnter:y,onEnter:_,onEnterCancelled:b,onLeave:S,onLeaveCancelled:C,onBeforeAppear:T=y,onAppear:k=_,onAppearCancelled:E=b}=t,w=(e,t,n,r)=>{e._enterCancelled=r,nl(e,t?u:c),nl(e,t?a:i),n&&n()},A=(e,t)=>{e._isLeaving=!1,nl(e,d),nl(e,h),nl(e,p),t&&t()},N=e=>(t,n)=>{const o=e?k:_,i=()=>w(t,e,n);Xc(o,[t,i]),rl(()=>{nl(t,e?l:s),tl(t,e?u:c),Qc(o)||sl(t,r,g,i)})};return f(t,{onBeforeEnter(e){Xc(y,[e]),tl(e,s),tl(e,i)},onBeforeAppear(e){Xc(T,[e]),tl(e,l),tl(e,a)},onEnter:N(!1),onAppear:N(!0),onLeave(e,t){e._isLeaving=!0;const n=()=>A(e,t);tl(e,d),e._enterCancelled?(tl(e,p),al()):(al(),tl(e,p)),rl(()=>{e._isLeaving&&(nl(e,d),tl(e,h),Qc(S)||sl(e,r,v,n))}),Xc(S,[e,n])},onEnterCancelled(e){w(e,!1,void 0,!0),Xc(b,[e])},onAppearCancelled(e){w(e,!0,void 0,!0),Xc(E,[e])},onLeaveCancelled(e){A(e),Xc(C,[e])}})}function el(e){return H(e)}function tl(e,t){t.split(/\s+/).forEach(t=>t&&e.classList.add(t)),(e[Kc]||(e[Kc]=new Set)).add(t)}function nl(e,t){t.split(/\s+/).forEach(t=>t&&e.classList.remove(t));const n=e[Kc];n&&(n.delete(t),n.size||(e[Kc]=void 0))}function rl(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let ol=0;function sl(e,t,n,r){const o=e._endId=++ol,s=()=>{o===e._endId&&r()};if(null!=n)return setTimeout(s,n);const{type:i,timeout:c,propCount:l}=il(e,t);if(!i)return r();const a=i+"end";let u=0;const f=()=>{e.removeEventListener(a,d),s()},d=t=>{t.target===e&&++u>=l&&f()};setTimeout(()=>{u(n[e]||"").split(", "),o=r(`${Wc}Delay`),s=r(`${Wc}Duration`),i=cl(o,s),c=r(`${zc}Delay`),l=r(`${zc}Duration`),a=cl(c,l);let u=null,f=0,d=0;t===Wc?i>0&&(u=Wc,f=i,d=s.length):t===zc?a>0&&(u=zc,f=a,d=l.length):(f=Math.max(i,a),u=f>0?i>a?Wc:zc:null,d=u?u===Wc?s.length:l.length:0);return{type:u,timeout:f,propCount:d,hasTransform:u===Wc&&/\b(transform|all)(,|$)/.test(r(`${Wc}Property`).toString())}}function cl(e,t){for(;e.lengthll(t)+ll(e[n])))}function ll(e){return"auto"===e?0:1e3*Number(e.slice(0,-1).replace(",","."))}function al(){return document.body.offsetHeight}const ul=Symbol("_vod"),fl=Symbol("_vsh"),dl={beforeMount(e,{value:t},{transition:n}){e[ul]="none"===e.style.display?"":e.style.display,n&&t?n.beforeEnter(e):pl(e,t)},mounted(e,{value:t},{transition:n}){n&&t&&n.enter(e)},updated(e,{value:t,oldValue:n},{transition:r}){!t!=!n&&(r?t?(r.beforeEnter(e),pl(e,!0),r.enter(e)):r.leave(e,()=>{pl(e,!1)}):pl(e,t))},beforeUnmount(e,{value:t}){pl(e,t)}};function pl(e,t){e.style.display=t?e[ul]:"none",e[fl]=!t}const hl=Symbol("");function ml(e){const t=rc();if(!t)return;const n=t.ut=(n=e(t.proxy))=>{Array.from(document.querySelectorAll(`[data-v-owner="${t.uid}"]`)).forEach(e=>vl(e,n))};const r=()=>{const r=e(t.proxy);t.ce?vl(t.ce,r):gl(t.subTree,r),n(r)};mo(()=>{Bn(r)}),ho(()=>{Qs(r,c,{flush:"post"});const e=new MutationObserver(r);e.observe(t.subTree.el.parentNode,{childList:!0}),yo(()=>e.disconnect())})}function gl(e,t){if(128&e.shapeFlag){const n=e.suspense;e=n.activeBranch,n.pendingBranch&&!n.isHydrating&&n.effects.push(()=>{gl(n.activeBranch,t)})}for(;e.component;)e=e.component.subTree;if(1&e.shapeFlag&&e.el)vl(e.el,t);else if(e.type===Si)e.children.forEach(e=>gl(e,t));else if(e.type===Ti){let{el:n,anchor:r}=e;for(;n&&(vl(n,t),n!==r);)n=n.nextSibling}}function vl(e,t){if(1===e.nodeType){const n=e.style;let r="";for(const e in t){const o=ve(t[e]);n.setProperty(`--${e}`,o),r+=`--${e}: ${o};`}n[hl]=r}}const yl=/(^|;)\s*display\s*:/;const _l=/\s*!important$/;function bl(e,t,n){if(m(n))n.forEach(n=>bl(e,t,n));else if(null==n&&(n=""),t.startsWith("--"))e.setProperty(t,n);else{const r=function(e,t){const n=xl[t];if(n)return n;let r=M(t);if("filter"!==r&&r in e)return xl[t]=r;r=L(r);for(let n=0;n{if(e._vts){if(e._vts<=n.attached)return}else e._vts=Date.now();An(function(e,t){if(m(t)){const n=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{n.call(e),e._stopped=!0},t.map(e=>t=>!t._stopped&&e&&e(t))}return t}(e,n.value),t,5,[e])};return n.value=e,n.attached=Ol(),n}(r,o);El(e,n,i,c)}else i&&(!function(e,t,n,r){e.removeEventListener(t,n,r)}(e,n,i,c),s[t]=void 0)}}const Nl=/(?:Once|Passive|Capture)$/;let Il=0;const Rl=Promise.resolve(),Ol=()=>Il||(Rl.then(()=>Il=0),Il=Date.now());const Ml=e=>111===e.charCodeAt(0)&&110===e.charCodeAt(1)&&e.charCodeAt(2)>96&&e.charCodeAt(2)<123;const Pl={}; +/*! #__NO_SIDE_EFFECTS__ */function Dl(e,t,n){const r=Nr(e,t);w(r)&&f(r,t);class o extends Fl{constructor(e){super(r,e,n)}}return o.def=r,o} +/*! #__NO_SIDE_EFFECTS__ */const Ll=(e,t)=>Dl(e,t,Ta),$l="undefined"!=typeof HTMLElement?HTMLElement:class{};class Fl extends $l{constructor(e,t={},n=Ca){super(),this._def=e,this._props=t,this._createApp=n,this._isVueCE=!0,this._instance=null,this._app=null,this._nonce=this._def.nonce,this._connected=!1,this._resolved=!1,this._numberProps=null,this._styleChildren=new WeakSet,this._ob=null,this.shadowRoot&&n!==Ca?this._root=this.shadowRoot:!1!==e.shadowRoot?(this.attachShadow({mode:"open"}),this._root=this.shadowRoot):this._root=this}connectedCallback(){if(!this.isConnected)return;this.shadowRoot||this._resolved||this._parseSlots(),this._connected=!0;let e=this;for(;e=e&&(e.parentNode||e.host);)if(e instanceof Fl){this._parent=e;break}this._instance||(this._resolved?this._mount(this._def):e&&e._pendingResolve?this._pendingResolve=e._pendingResolve.then(()=>{this._pendingResolve=void 0,this._resolveDef()}):this._resolveDef())}_setParent(e=this._parent){e&&(this._instance.parent=e._instance,this._inheritParentContext(e))}_inheritParentContext(e=this._parent){e&&this._app&&Object.setPrototypeOf(this._app._context.provides,e._instance.provides)}disconnectedCallback(){this._connected=!1,$n(()=>{this._connected||(this._ob&&(this._ob.disconnect(),this._ob=null),this._app&&this._app.unmount(),this._instance&&(this._instance.ce=void 0),this._app=this._instance=null)})}_resolveDef(){if(this._pendingResolve)return;for(let e=0;e{for(const t of e)this._setAttr(t.attributeName)}),this._ob.observe(this,{attributes:!0});const e=(e,t=!1)=>{this._resolved=!0,this._pendingResolve=void 0;const{props:n,styles:r}=e;let o;if(n&&!m(n))for(const e in n){const t=n[e];(t===Number||t&&t.type===Number)&&(e in this._props&&(this._props[e]=H(this._props[e])),(o||(o=Object.create(null)))[M(e)]=!0)}this._numberProps=o,this._resolveProps(e),this.shadowRoot&&this._applyStyles(r),this._mount(e)},t=this._def.__asyncLoader;t?this._pendingResolve=t().then(t=>{t.configureApp=this._def.configureApp,e(this._def=t,!0)}):e(this._def)}_mount(e){this._app=this._createApp(e),this._inheritParentContext(),e.configureApp&&e.configureApp(this._app),this._app._ceVNode=this._createVNode(),this._app.mount(this._root);const t=this._instance&&this._instance.exposed;if(t)for(const e in t)h(this,e)||Object.defineProperty(this,e,{get:()=>Qt(t[e])})}_resolveProps(e){const{props:t}=e,n=m(t)?t:Object.keys(t||{});for(const e of Object.keys(this))"_"!==e[0]&&n.includes(e)&&this._setProp(e,this[e]);for(const e of n.map(M))Object.defineProperty(this,e,{get(){return this._getProp(e)},set(t){this._setProp(e,t,!0,!0)}})}_setAttr(e){if(e.startsWith("data-v-"))return;const t=this.hasAttribute(e);let n=t?this.getAttribute(e):Pl;const r=M(e);t&&this._numberProps&&this._numberProps[r]&&(n=H(n)),this._setProp(r,n,!1,!0)}_getProp(e){return this._props[e]}_setProp(e,t,n=!0,r=!1){if(t!==this._props[e]&&(t===Pl?delete this._props[e]:(this._props[e]=t,"key"===e&&this._app&&(this._app._ceVNode.key=t)),r&&this._instance&&this._update(),n)){const n=this._ob;n&&n.disconnect(),!0===t?this.setAttribute(D(e),""):"string"==typeof t||"number"==typeof t?this.setAttribute(D(e),t+""):t||this.removeAttribute(D(e)),n&&n.observe(this,{attributes:!0})}}_update(){const e=this._createVNode();this._app&&(e.appContext=this._app._context),Sa(e,this._root)}_createVNode(){const e={};this.shadowRoot||(e.onVnodeMounted=e.onVnodeUpdated=this._renderSlots.bind(this));const t=Ui(this._def,f(e,this._props));return this._instance||(t.ce=e=>{this._instance=e,e.ce=this,e.isCE=!0;const t=(e,t)=>{this.dispatchEvent(new CustomEvent(e,w(t[0])?f({detail:t},t[0]):{detail:t}))};e.emit=(e,...n)=>{t(e,n),D(e)!==e&&t(D(e),n)},this._setParent()}),t}_applyStyles(e,t){if(!e)return;if(t){if(t===this._def||this._styleChildren.has(t))return;this._styleChildren.add(t)}const n=this._nonce;for(let t=e.length-1;t>=0;t--){const r=document.createElement("style");n&&r.setAttribute("nonce",n),r.textContent=e[t],this.shadowRoot.prepend(r)}}_parseSlots(){const e=this._slots={};let t;for(;t=this.firstChild;){const n=1===t.nodeType&&t.getAttribute("slot")||"default";(e[n]||(e[n]=[])).push(t),this.removeChild(t)}}_renderSlots(){const e=(this._teleportTarget||this).querySelectorAll("slot"),t=this._instance.type.__scopeId;for(let n=0;n(delete e.props.mode,e))({name:"TransitionGroup",props:f({},Yc,{tag:String,moveClass:String}),setup(e,{slots:t}){const n=rc(),r=vr();let o,s;return go(()=>{if(!o.length)return;const t=e.moveClass||`${e.name||"v"}-move`;if(!function(e,t,n){const r=e.cloneNode(),o=e[Kc];o&&o.forEach(e=>{e.split(/\s+/).forEach(e=>e&&r.classList.remove(e))});n.split(/\s+/).forEach(e=>e&&r.classList.add(e)),r.style.display="none";const s=1===t.nodeType?t:t.parentNode;s.appendChild(r);const{hasTransform:i}=il(r);return s.removeChild(r),i}(o[0].el,n.vnode.el,t))return void(o=[]);o.forEach(Kl),o.forEach(Jl);const r=o.filter(Yl);al(),r.forEach(e=>{const n=e.el,r=n.style;tl(n,t),r.transform=r.webkitTransform=r.transitionDuration="";const o=n[ql]=e=>{e&&e.target!==n||e&&!/transform$/.test(e.propertyName)||(n.removeEventListener("transitionend",o),n[ql]=null,nl(n,t))};n.addEventListener("transitionend",o)}),o=[]}),()=>{const i=Ht(e),c=Zc(i);let l=i.tag||Si;if(o=[],s)for(let e=0;e{const t=e.props["onUpdate:modelValue"]||!1;return m(t)?e=>V(t,e):t};function Xl(e){e.target.composing=!0}function Ql(e){const t=e.target;t.composing&&(t.composing=!1,t.dispatchEvent(new Event("input")))}const Zl=Symbol("_assign"),ea={created(e,{modifiers:{lazy:t,trim:n,number:r}},o){e[Zl]=Gl(o);const s=r||o.props&&"number"===o.props.type;El(e,t?"change":"input",t=>{if(t.target.composing)return;let r=e.value;n&&(r=r.trim()),s&&(r=U(r)),e[Zl](r)}),n&&El(e,"change",()=>{e.value=e.value.trim()}),t||(El(e,"compositionstart",Xl),El(e,"compositionend",Ql),El(e,"change",Ql))},mounted(e,{value:t}){e.value=null==t?"":t},beforeUpdate(e,{value:t,oldValue:n,modifiers:{lazy:r,trim:o,number:s}},i){if(e[Zl]=Gl(i),e.composing)return;const c=null==t?"":t;if((!s&&"number"!==e.type||/^0\d/.test(e.value)?e.value:U(e.value))!==c){if(document.activeElement===e&&"range"!==e.type){if(r&&t===n)return;if(o&&e.value.trim()===c)return}e.value=c}}},ta={deep:!0,created(e,t,n){e[Zl]=Gl(n),El(e,"change",()=>{const t=e._modelValue,n=ia(e),r=e.checked,o=e[Zl];if(m(t)){const e=de(t,n),s=-1!==e;if(r&&!s)o(t.concat(n));else if(!r&&s){const n=[...t];n.splice(e,1),o(n)}}else if(v(t)){const e=new Set(t);r?e.add(n):e.delete(n),o(e)}else o(ca(e,r))})},mounted:na,beforeUpdate(e,t,n){e[Zl]=Gl(n),na(e,t,n)}};function na(e,{value:t,oldValue:n},r){let o;if(e._modelValue=t,m(t))o=de(t,r.props.value)>-1;else if(v(t))o=t.has(r.props.value);else{if(t===n)return;o=fe(t,ca(e,!0))}e.checked!==o&&(e.checked=o)}const ra={created(e,{value:t},n){e.checked=fe(t,n.props.value),e[Zl]=Gl(n),El(e,"change",()=>{e[Zl](ia(e))})},beforeUpdate(e,{value:t,oldValue:n},r){e[Zl]=Gl(r),t!==n&&(e.checked=fe(t,r.props.value))}},oa={deep:!0,created(e,{value:t,modifiers:{number:n}},r){const o=v(t);El(e,"change",()=>{const t=Array.prototype.filter.call(e.options,e=>e.selected).map(e=>n?U(ia(e)):ia(e));e[Zl](e.multiple?o?new Set(t):t:t[0]),e._assigning=!0,$n(()=>{e._assigning=!1})}),e[Zl]=Gl(r)},mounted(e,{value:t}){sa(e,t)},beforeUpdate(e,t,n){e[Zl]=Gl(n)},updated(e,{value:t}){e._assigning||sa(e,t)}};function sa(e,t){const n=e.multiple,r=m(t);if(!n||r||v(t)){for(let o=0,s=e.options.length;oString(e)===String(i)):de(t,i)>-1}else s.selected=t.has(i);else if(fe(ia(s),t))return void(e.selectedIndex!==o&&(e.selectedIndex=o))}n||-1===e.selectedIndex||(e.selectedIndex=-1)}}function ia(e){return"_value"in e?e._value:e.value}function ca(e,t){const n=t?"_trueValue":"_falseValue";return n in e?e[n]:t}const la={created(e,t,n){ua(e,t,n,null,"created")},mounted(e,t,n){ua(e,t,n,null,"mounted")},beforeUpdate(e,t,n,r){ua(e,t,n,r,"beforeUpdate")},updated(e,t,n,r){ua(e,t,n,r,"updated")}};function aa(e,t){switch(e){case"SELECT":return oa;case"TEXTAREA":return ea;default:switch(t){case"checkbox":return ta;case"radio":return ra;default:return ea}}}function ua(e,t,n,r,o){const s=aa(e.tagName,n.props&&n.props.type)[o];s&&s(e,t,n,r)}const fa=["ctrl","shift","alt","meta"],da={stop:e=>e.stopPropagation(),prevent:e=>e.preventDefault(),self:e=>e.target!==e.currentTarget,ctrl:e=>!e.ctrlKey,shift:e=>!e.shiftKey,alt:e=>!e.altKey,meta:e=>!e.metaKey,left:e=>"button"in e&&0!==e.button,middle:e=>"button"in e&&1!==e.button,right:e=>"button"in e&&2!==e.button,exact:(e,t)=>fa.some(n=>e[`${n}Key`]&&!t.includes(n))},pa=(e,t)=>{const n=e._withMods||(e._withMods={}),r=t.join(".");return n[r]||(n[r]=(n,...r)=>{for(let e=0;e{const n=e._withKeys||(e._withKeys={}),r=t.join(".");return n[r]||(n[r]=n=>{if(!("key"in n))return;const r=D(n.key);return t.some(e=>e===r||ha[e]===r)?e(n):void 0})},ga=f({patchProp:(e,t,n,r,o,s)=>{const i="svg"===o;"class"===t?function(e,t,n){const r=e[Kc];r&&(t=(t?[t,...r]:[...r]).join(" ")),null==t?e.removeAttribute("class"):n?e.setAttribute("class",t):e.className=t}(e,r,i):"style"===t?function(e,t,n){const r=e.style,o=b(n);let s=!1;if(n&&!o){if(t)if(b(t))for(const e of t.split(";")){const t=e.slice(0,e.indexOf(":")).trim();null==n[t]&&bl(r,t,"")}else for(const e in t)null==n[e]&&bl(r,e,"");for(const e in n)"display"===e&&(s=!0),bl(r,e,n[e])}else if(o){if(t!==n){const e=r[hl];e&&(n+=";"+e),r.cssText=n,s=yl.test(n)}}else t&&e.removeAttribute("style");ul in e&&(e[ul]=s?r.display:"",e[fl]&&(r.display="none"))}(e,n,r):a(t)?u(t)||Al(e,t,0,r,s):("."===t[0]?(t=t.slice(1),1):"^"===t[0]?(t=t.slice(1),0):function(e,t,n,r){if(r)return"innerHTML"===t||"textContent"===t||!!(t in e&&Ml(t)&&_(n));if("spellcheck"===t||"draggable"===t||"translate"===t||"autocorrect"===t)return!1;if("form"===t)return!1;if("list"===t&&"INPUT"===e.tagName)return!1;if("type"===t&&"TEXTAREA"===e.tagName)return!1;if("width"===t||"height"===t){const t=e.tagName;if("IMG"===t||"VIDEO"===t||"CANVAS"===t||"SOURCE"===t)return!1}if(Ml(t)&&b(n))return!1;return t in e}(e,t,r,i))?(kl(e,t,r),e.tagName.includes("-")||"value"!==t&&"checked"!==t&&"selected"!==t||Tl(e,t,r,i,0,"value"!==t)):!e._isVueCE||!/[A-Z]/.test(t)&&b(r)?("true-value"===t?e._trueValue=r:"false-value"===t&&(e._falseValue=r),Tl(e,t,r,i)):kl(e,M(t),r,0,t)}},qc);let va,ya=!1;function _a(){return va||(va=Fs(ga))}function ba(){return va=ya?va:Vs(ga),ya=!0,va}const Sa=(...e)=>{_a().render(...e)},xa=(...e)=>{ba().hydrate(...e)},Ca=(...e)=>{const t=_a().createApp(...e);const{mount:n}=t;return t.mount=e=>{const r=Ea(e);if(!r)return;const o=t._component;_(o)||o.render||o.template||(o.template=r.innerHTML),1===r.nodeType&&(r.textContent="");const s=n(r,!1,ka(r));return r instanceof Element&&(r.removeAttribute("v-cloak"),r.setAttribute("data-v-app","")),s},t},Ta=(...e)=>{const t=ba().createApp(...e);const{mount:n}=t;return t.mount=e=>{const t=Ea(e);if(t)return n(t,!0,ka(t))},t};function ka(e){return e instanceof SVGElement?"svg":"function"==typeof MathMLElement&&e instanceof MathMLElement?"mathml":void 0}function Ea(e){if(b(e)){return document.querySelector(e)}return e}let wa=!1;const Aa=()=>{wa||(wa=!0,ea.getSSRProps=({value:e})=>({value:e}),ra.getSSRProps=({value:e},t)=>{if(t.props&&fe(t.props.value,e))return{checked:!0}},ta.getSSRProps=({value:e},t)=>{if(m(e)){if(t.props&&de(e,t.props.value)>-1)return{checked:!0}}else if(v(e)){if(t.props&&e.has(t.props.value))return{checked:!0}}else if(e)return{checked:!0}},la.getSSRProps=(e,t)=>{if("string"!=typeof t.type)return;const n=aa(t.type.toUpperCase(),t.props&&t.props.type);return n.getSSRProps?n.getSSRProps(e,t):void 0},dl.getSSRProps=({value:e})=>{if(!e)return{style:{display:"none"}}})},Na=Symbol(""),Ia=Symbol(""),Ra=Symbol(""),Oa=Symbol(""),Ma=Symbol(""),Pa=Symbol(""),Da=Symbol(""),La=Symbol(""),$a=Symbol(""),Fa=Symbol(""),Va=Symbol(""),Ba=Symbol(""),Ua=Symbol(""),Ha=Symbol(""),ja=Symbol(""),qa=Symbol(""),Wa=Symbol(""),za=Symbol(""),Ka=Symbol(""),Ja=Symbol(""),Ya=Symbol(""),Ga=Symbol(""),Xa=Symbol(""),Qa=Symbol(""),Za=Symbol(""),eu=Symbol(""),tu=Symbol(""),nu=Symbol(""),ru=Symbol(""),ou=Symbol(""),su=Symbol(""),iu=Symbol(""),cu=Symbol(""),lu=Symbol(""),au=Symbol(""),uu=Symbol(""),fu=Symbol(""),du=Symbol(""),pu=Symbol(""),hu={[Na]:"Fragment",[Ia]:"Teleport",[Ra]:"Suspense",[Oa]:"KeepAlive",[Ma]:"BaseTransition",[Pa]:"openBlock",[Da]:"createBlock",[La]:"createElementBlock",[$a]:"createVNode",[Fa]:"createElementVNode",[Va]:"createCommentVNode",[Ba]:"createTextVNode",[Ua]:"createStaticVNode",[Ha]:"resolveComponent",[ja]:"resolveDynamicComponent",[qa]:"resolveDirective",[Wa]:"resolveFilter",[za]:"withDirectives",[Ka]:"renderList",[Ja]:"renderSlot",[Ya]:"createSlots",[Ga]:"toDisplayString",[Xa]:"mergeProps",[Qa]:"normalizeClass",[Za]:"normalizeStyle",[eu]:"normalizeProps",[tu]:"guardReactiveProps",[nu]:"toHandlers",[ru]:"camelize",[ou]:"capitalize",[su]:"toHandlerKey",[iu]:"setBlockTracking",[cu]:"pushScopeId",[lu]:"popScopeId",[au]:"withCtx",[uu]:"unref",[fu]:"isRef",[du]:"withMemo",[pu]:"isMemoSame"};const mu={start:{line:1,column:1,offset:0},end:{line:1,column:1,offset:0},source:""};function gu(e,t,n,r,o,s,i,c=!1,l=!1,a=!1,u=mu){return e&&(c?(e.helper(Pa),e.helper(Eu(e.inSSR,a))):e.helper(ku(e.inSSR,a)),i&&e.helper(za)),{type:13,tag:t,props:n,children:r,patchFlag:o,dynamicProps:s,directives:i,isBlock:c,disableTracking:l,isComponent:a,loc:u}}function vu(e,t=mu){return{type:17,loc:t,elements:e}}function yu(e,t=mu){return{type:15,loc:t,properties:e}}function _u(e,t){return{type:16,loc:mu,key:b(e)?bu(e,!0):e,value:t}}function bu(e,t=!1,n=mu,r=0){return{type:4,loc:n,content:e,isStatic:t,constType:t?3:r}}function Su(e,t=mu){return{type:8,loc:t,children:e}}function xu(e,t=[],n=mu){return{type:14,loc:n,callee:e,arguments:t}}function Cu(e,t=void 0,n=!1,r=!1,o=mu){return{type:18,params:e,returns:t,newline:n,isSlot:r,loc:o}}function Tu(e,t,n,r=!0){return{type:19,test:e,consequent:t,alternate:n,newline:r,loc:mu}}function ku(e,t){return e||t?$a:Fa}function Eu(e,t){return e||t?Da:La}function wu(e,{helper:t,removeHelper:n,inSSR:r}){e.isBlock||(e.isBlock=!0,n(ku(r,e.isComponent)),t(Pa),t(Eu(r,e.isComponent)))}const Au=new Uint8Array([123,123]),Nu=new Uint8Array([125,125]);function Iu(e){return e>=97&&e<=122||e>=65&&e<=90}function Ru(e){return 32===e||10===e||9===e||12===e||13===e}function Ou(e){return 47===e||62===e||Ru(e)}function Mu(e){const t=new Uint8Array(e.length);for(let n=0;n4===e.type&&e.isStatic;function Hu(e){switch(e){case"Teleport":case"teleport":return Ia;case"Suspense":case"suspense":return Ra;case"KeepAlive":case"keep-alive":return Oa;case"BaseTransition":case"base-transition":return Ma}}const ju=/^$|^\d|[^\$\w\xA0-\uFFFF]/,qu=e=>!ju.test(e),Wu=/[A-Za-z_$\xA0-\uFFFF]/,zu=/[\.\?\w$\xA0-\uFFFF]/,Ku=/\s+[.[]\s*|\s*[.[]\s+/g,Ju=e=>4===e.type?e.content:e.loc.source,Yu=e=>{const t=Ju(e).trim().replace(Ku,e=>e.trim());let n=0,r=[],o=0,s=0,i=null;for(let e=0;e|^\s*(async\s+)?function(?:\s+[\w$]+)?\s*\(/,Xu=e=>Gu.test(Ju(e));function Qu(e,t,n=!1){for(let r=0;r4===e.key.type&&e.key.content===r)}return n}function ff(e,t){return`_${t}_${e.replace(/[^\w]/g,(t,n)=>"-"===t?"_":e.charCodeAt(n).toString())}`}const df=/([\s\S]*?)\s+(?:in|of)\s+(\S[\s\S]*)/,pf={parseMode:"base",ns:0,delimiters:["{{","}}"],getNamespace:()=>0,isVoidTag:l,isPreTag:l,isIgnoreNewlineTag:l,isCustomElement:l,onError:Fu,onWarn:Vu,comments:!1,prefixIdentifiers:!1};let hf=pf,mf=null,gf="",vf=null,yf=null,_f="",bf=-1,Sf=-1,xf=0,Cf=!1,Tf=null;const kf=[],Ef=new class{constructor(e,t){this.stack=e,this.cbs=t,this.state=1,this.buffer="",this.sectionStart=0,this.index=0,this.entityStart=0,this.baseState=1,this.inRCDATA=!1,this.inXML=!1,this.inVPre=!1,this.newlines=[],this.mode=0,this.delimiterOpen=Au,this.delimiterClose=Nu,this.delimiterIndex=-1,this.currentSequence=void 0,this.sequenceIndex=0}get inSFCRoot(){return 2===this.mode&&0===this.stack.length}reset(){this.state=1,this.mode=0,this.buffer="",this.sectionStart=0,this.index=0,this.baseState=1,this.inRCDATA=!1,this.currentSequence=void 0,this.newlines.length=0,this.delimiterOpen=Au,this.delimiterClose=Nu}getPos(e){let t=1,n=e+1;for(let r=this.newlines.length-1;r>=0;r--){const o=this.newlines[r];if(e>o){t=r+2,n=e-o;break}}return{column:n,line:t,offset:e}}peek(){return this.buffer.charCodeAt(this.index+1)}stateText(e){60===e?(this.index>this.sectionStart&&this.cbs.ontext(this.sectionStart,this.index),this.state=5,this.sectionStart=this.index):this.inVPre||e!==this.delimiterOpen[0]||(this.state=2,this.delimiterIndex=0,this.stateInterpolationOpen(e))}stateInterpolationOpen(e){if(e===this.delimiterOpen[this.delimiterIndex])if(this.delimiterIndex===this.delimiterOpen.length-1){const e=this.index+1-this.delimiterOpen.length;e>this.sectionStart&&this.cbs.ontext(this.sectionStart,e),this.state=3,this.sectionStart=e}else this.delimiterIndex++;else this.inRCDATA?(this.state=32,this.stateInRCDATA(e)):(this.state=1,this.stateText(e))}stateInterpolation(e){e===this.delimiterClose[0]&&(this.state=4,this.delimiterIndex=0,this.stateInterpolationClose(e))}stateInterpolationClose(e){e===this.delimiterClose[this.delimiterIndex]?this.delimiterIndex===this.delimiterClose.length-1?(this.cbs.oninterpolation(this.sectionStart,this.index+1),this.inRCDATA?this.state=32:this.state=1,this.sectionStart=this.index+1):this.delimiterIndex++:(this.state=3,this.stateInterpolation(e))}stateSpecialStartSequence(e){const t=this.sequenceIndex===this.currentSequence.length;if(t?Ou(e):(32|e)===this.currentSequence[this.sequenceIndex]){if(!t)return void this.sequenceIndex++}else this.inRCDATA=!1;this.sequenceIndex=0,this.state=6,this.stateInTagName(e)}stateInRCDATA(e){if(this.sequenceIndex===this.currentSequence.length){if(62===e||Ru(e)){const t=this.index-this.currentSequence.length;if(this.sectionStart=e||(28===this.state?this.currentSequence===Pu.CdataEnd?this.cbs.oncdata(this.sectionStart,e):this.cbs.oncomment(this.sectionStart,e):6===this.state||11===this.state||18===this.state||17===this.state||12===this.state||13===this.state||14===this.state||15===this.state||16===this.state||20===this.state||19===this.state||21===this.state||9===this.state||this.cbs.ontext(this.sectionStart,e))}emitCodePoint(e,t){}}(kf,{onerr:Kf,ontext(e,t){Rf(Nf(e,t),e,t)},ontextentity(e,t,n){Rf(e,t,n)},oninterpolation(e,t){if(Cf)return Rf(Nf(e,t),e,t);let n=e+Ef.delimiterOpen.length,r=t-Ef.delimiterClose.length;for(;Ru(gf.charCodeAt(n));)n++;for(;Ru(gf.charCodeAt(r-1));)r--;let o=Nf(n,r);o.includes("&")&&(o=hf.decodeEntities(o,!1)),Uf({type:5,content:zf(o,!1,Hf(n,r)),loc:Hf(e,t)})},onopentagname(e,t){const n=Nf(e,t);vf={type:1,tag:n,ns:hf.getNamespace(n,kf[0],hf.ns),tagType:0,props:[],children:[],loc:Hf(e-1,t),codegenNode:void 0}},onopentagend(e){If(e)},onclosetag(e,t){const n=Nf(e,t);if(!hf.isVoidTag(n)){let r=!1;for(let e=0;e0&&Kf(24,kf[0].loc.start.offset);for(let n=0;n<=e;n++){Of(kf.shift(),t,n(7===e.type?e.rawName:e.name)===n)&&Kf(2,t)},onattribend(e,t){if(vf&&yf){if(qf(yf.loc,t),0!==e)if(_f.includes("&")&&(_f=hf.decodeEntities(_f,!0)),6===yf.type)"class"===yf.name&&(_f=Bf(_f).trim()),1!==e||_f||Kf(13,t),yf.value={type:2,content:_f,loc:1===e?Hf(bf,Sf):Hf(bf-1,Sf+1)},Ef.inSFCRoot&&"template"===vf.tag&&"lang"===yf.name&&_f&&"html"!==_f&&Ef.enterRCDATA(Mu("{const o=t.start.offset+n;return zf(e,!1,Hf(o,o+e.length),0,r?1:0)},c={source:i(s.trim(),n.indexOf(s,o.length)),value:void 0,key:void 0,index:void 0,finalized:!1};let l=o.trim().replace(Af,"").trim();const a=o.indexOf(l),u=l.match(wf);if(u){l=l.replace(wf,"").trim();const e=u[1].trim();let t;if(e&&(t=n.indexOf(e,a+l.length),c.key=i(e,t,!0)),u[2]){const r=u[2].trim();r&&(c.index=i(r,n.indexOf(r,c.key?t+e.length:a+l.length),!0))}}l&&(c.value=i(l,a,!0));return c}(yf.exp));let t=-1;"bind"===yf.name&&(t=yf.modifiers.findIndex(e=>"sync"===e.content))>-1&&$u("COMPILER_V_BIND_SYNC",hf,yf.loc,yf.arg.loc.source)&&(yf.name="model",yf.modifiers.splice(t,1))}7===yf.type&&"pre"===yf.name||vf.props.push(yf)}_f="",bf=Sf=-1},oncomment(e,t){hf.comments&&Uf({type:3,content:Nf(e,t),loc:Hf(e-4,t+3)})},onend(){const e=gf.length;for(let t=0;t64&&n<91)||Hu(e)||hf.isBuiltInComponent&&hf.isBuiltInComponent(e)||hf.isNativeTag&&!hf.isNativeTag(e))return!0;var n;for(let e=0;e6===e.type&&"inline-template"===e.name);n&&$u("COMPILER_INLINE_TEMPLATE",hf,n.loc)&&e.children.length&&(n.value={type:2,content:Nf(e.children[0].loc.start.offset,e.children[e.children.length-1].loc.end.offset),loc:n.loc})}}function Mf(e,t){let n=e;for(;gf.charCodeAt(n)!==t&&n>=0;)n--;return n}const Pf=new Set(["if","else","else-if","for","slot"]);function Df({tag:e,props:t}){if("template"===e)for(let e=0;e3!==e.type);return 1!==t.length||1!==t[0].type||sf(t[0])?null:t[0]}function Xf(e,t,n,r=!1,o=!1){const{children:s}=e,i=[];for(let t=0;t0){if(e>=2){c.codegenNode.patchFlag=-1,i.push(c);continue}}else{const e=c.codegenNode;if(13===e.type){const t=e.patchFlag;if((void 0===t||512===t||1===t)&&td(c,n)>=2){const t=nd(c);t&&(e.props=n.hoist(t))}e.dynamicProps&&(e.dynamicProps=n.hoist(e.dynamicProps))}}}else if(12===c.type){if((r?0:Qf(c,n))>=2){14===c.codegenNode.type&&c.codegenNode.arguments.length>0&&c.codegenNode.arguments.push("-1"),i.push(c);continue}}if(1===c.type){const t=1===c.tagType;t&&n.scopes.vSlot++,Xf(c,e,n,!1,o),t&&n.scopes.vSlot--}else if(11===c.type)Xf(c,e,n,1===c.children.length,!0);else if(9===c.type)for(let t=0;te.key===t||e.key.content===t);return n&&n.value}}l.length&&1===e.type&&1===e.tagType&&e.codegenNode&&13===e.codegenNode.type&&e.codegenNode.children&&!m(e.codegenNode.children)&&15===e.codegenNode.children.type&&e.codegenNode.children.properties.push(_u("__",bu(JSON.stringify(l),!1))),i.length&&n.transformHoist&&n.transformHoist(s,n,e)}function Qf(e,t){const{constantCache:n}=t;switch(e.type){case 1:if(0!==e.tagType)return 0;const r=n.get(e);if(void 0!==r)return r;const o=e.codegenNode;if(13!==o.type)return 0;if(o.isBlock&&"svg"!==e.tag&&"foreignObject"!==e.tag&&"math"!==e.tag)return 0;if(void 0===o.patchFlag){let r=3;const s=td(e,t);if(0===s)return n.set(e,0),0;s1)for(let o=0;on&&(w.childIndex--,w.onNodeRemoved()):(w.currentNode=null,w.onNodeRemoved()),w.parent.children.splice(n,1)},onNodeRemoved:c,addIdentifiers(e){},removeIdentifiers(e){},hoist(e){b(e)&&(e=bu(e)),w.hoists.push(e);const t=bu(`_hoisted_${w.hoists.length}`,!1,e.loc,2);return t.hoisted=e,t},cache(e,t=!1,n=!1){const r=function(e,t,n=!1,r=!1){return{type:20,index:e,value:t,needPauseTracking:n,inVOnce:r,needArraySpread:!1,loc:mu}}(w.cached.length,e,t,n);return w.cached.push(r),r}};return w.filters=new Set,w}function od(e,t){const n=rd(e,t);sd(e,n),t.hoistStatic&&Yf(e,n),t.ssr||function(e,t){const{helper:n}=t,{children:r}=e;if(1===r.length){const n=Gf(e);if(n&&n.codegenNode){const r=n.codegenNode;13===r.type&&wu(r,t),e.codegenNode=r}else e.codegenNode=r[0]}else if(r.length>1){let r=64;0,e.codegenNode=gu(t,n(Na),void 0,e.children,r,void 0,void 0,!0,void 0,!1)}}(e,n),e.helpers=new Set([...n.helpers.keys()]),e.components=[...n.components],e.directives=[...n.directives],e.imports=n.imports,e.hoists=n.hoists,e.temps=n.temps,e.cached=n.cached,e.transformed=!0,e.filters=[...n.filters]}function sd(e,t){t.currentNode=e;const{nodeTransforms:n}=t,r=[];for(let o=0;o{n--};for(;nt===e:t=>e.test(t);return(e,r)=>{if(1===e.type){const{props:o}=e;if(3===e.tagType&&o.some(rf))return;const s=[];for(let i=0;i`${hu[e]}: _${hu[e]}`;function ad(e,t={}){const n=function(e,{mode:t="function",prefixIdentifiers:n="module"===t,sourceMap:r=!1,filename:o="template.vue.html",scopeId:s=null,optimizeImports:i=!1,runtimeGlobalName:c="Vue",runtimeModuleName:l="vue",ssrRuntimeModuleName:a="vue/server-renderer",ssr:u=!1,isTS:f=!1,inSSR:d=!1}){const p={mode:t,prefixIdentifiers:n,sourceMap:r,filename:o,scopeId:s,optimizeImports:i,runtimeGlobalName:c,runtimeModuleName:l,ssrRuntimeModuleName:a,ssr:u,isTS:f,inSSR:d,source:e.source,code:"",column:1,line:1,offset:0,indentLevel:0,pure:!1,map:void 0,helper(e){return`_${hu[e]}`},push(e,t=-2,n){p.code+=e},indent(){h(++p.indentLevel)},deindent(e=!1){e?--p.indentLevel:h(--p.indentLevel)},newline(){h(p.indentLevel)}};function h(e){p.push("\n"+" ".repeat(e),0)}return p}(e,t);t.onContextCreated&&t.onContextCreated(n);const{mode:r,push:o,prefixIdentifiers:s,indent:i,deindent:c,newline:l,scopeId:a,ssr:u}=n,f=Array.from(e.helpers),d=f.length>0,p=!s&&"module"!==r;!function(e,t){const{ssr:n,prefixIdentifiers:r,push:o,newline:s,runtimeModuleName:i,runtimeGlobalName:c,ssrRuntimeModuleName:l}=t,a=c,u=Array.from(e.helpers);if(u.length>0&&(o(`const _Vue = ${a}\n`,-1),e.hoists.length)){o(`const { ${[$a,Fa,Va,Ba,Ua].filter(e=>u.includes(e)).map(ld).join(", ")} } = _Vue\n`,-1)}(function(e,t){if(!e.length)return;t.pure=!0;const{push:n,newline:r}=t;r();for(let o=0;o0)&&l()),e.directives.length&&(ud(e.directives,"directive",n),e.temps>0&&l()),e.filters&&e.filters.length&&(l(),ud(e.filters,"filter",n),l()),e.temps>0){o("let ");for(let t=0;t0?", ":""}_temp${t}`)}return(e.components.length||e.directives.length||e.temps)&&(o("\n",0),l()),u||o("return "),e.codegenNode?pd(e.codegenNode,n):o("null"),p&&(c(),o("}")),c(),o("}"),{ast:e,code:n.code,preamble:"",map:n.map?n.map.toJSON():void 0}}function ud(e,t,{helper:n,push:r,newline:o,isTS:s}){const i=n("filter"===t?Wa:"component"===t?Ha:qa);for(let n=0;n3||!1;t.push("["),n&&t.indent(),dd(e,t,n),n&&t.deindent(),t.push("]")}function dd(e,t,n=!1,r=!0){const{push:o,newline:s}=t;for(let i=0;ie||"null")}([s,i,c,h,a]),t),n(")"),f&&n(")");u&&(n(", "),pd(u,t),n(")"))}(e,t);break;case 14:!function(e,t){const{push:n,helper:r,pure:o}=t,s=b(e.callee)?e.callee:r(e.callee);o&&n(cd);n(s+"(",-2,e),dd(e.arguments,t),n(")")}(e,t);break;case 15:!function(e,t){const{push:n,indent:r,deindent:o,newline:s}=t,{properties:i}=e;if(!i.length)return void n("{}",-2,e);const c=i.length>1||!1;n(c?"{":"{ "),c&&r();for(let e=0;e "),(l||c)&&(n("{"),r());i?(l&&n("return "),m(i)?fd(i,t):pd(i,t)):c&&pd(c,t);(l||c)&&(o(),n("}"));a&&(e.isNonScopedSlot&&n(", undefined, true"),n(")"))}(e,t);break;case 19:!function(e,t){const{test:n,consequent:r,alternate:o,newline:s}=e,{push:i,indent:c,deindent:l,newline:a}=t;if(4===n.type){const e=!qu(n.content);e&&i("("),hd(n,t),e&&i(")")}else i("("),pd(n,t),i(")");s&&c(),t.indentLevel++,s||i(" "),i("? "),pd(r,t),t.indentLevel--,s&&a(),s||i(" "),i(": ");const u=19===o.type;u||t.indentLevel++;pd(o,t),u||t.indentLevel--;s&&l(!0)}(e,t);break;case 20:!function(e,t){const{push:n,helper:r,indent:o,deindent:s,newline:i}=t,{needPauseTracking:c,needArraySpread:l}=e;l&&n("[...(");n(`_cache[${e.index}] || (`),c&&(o(),n(`${r(iu)}(-1`),e.inVOnce&&n(", true"),n("),"),i(),n("("));n(`_cache[${e.index}] = `),pd(e.value,t),c&&(n(`).cacheIndex = ${e.index},`),i(),n(`${r(iu)}(1),`),i(),n(`_cache[${e.index}]`),s());n(")"),l&&n(")]")}(e,t);break;case 21:dd(e.body,t,!0,!1)}}function hd(e,t){const{content:n,isStatic:r}=e;t.push(r?JSON.stringify(n):n,-3,e)}function md(e,t){for(let n=0;nfunction(e,t,n,r){if(!("else"===t.name||t.exp&&t.exp.content.trim())){const r=t.exp?t.exp.loc:e.loc;n.onError(Bu(28,t.loc)),t.exp=bu("true",!1,r)}0;if("if"===t.name){const o=yd(e,t),s={type:9,loc:jf(e.loc),branches:[o]};if(n.replaceNode(s),r)return r(s,o,!0)}else{const o=n.parent.children;let s=o.indexOf(e);for(;s-- >=-1;){const i=o[s];if(i&&3===i.type)n.removeNode(i);else{if(!i||2!==i.type||i.content.trim().length){if(i&&9===i.type){"else-if"===t.name&&void 0===i.branches[i.branches.length-1].condition&&n.onError(Bu(30,e.loc)),n.removeNode();const o=yd(e,t);0,i.branches.push(o);const s=r&&r(i,o,!1);sd(o,n),s&&s(),n.currentNode=null}else n.onError(Bu(30,e.loc));break}n.removeNode(i)}}}}(e,t,n,(e,t,r)=>{const o=n.parent.children;let s=o.indexOf(e),i=0;for(;s-- >=0;){const e=o[s];e&&9===e.type&&(i+=e.branches.length)}return()=>{if(r)e.codegenNode=_d(t,i,n);else{const r=function(e){for(;;)if(19===e.type){if(19!==e.alternate.type)return e;e=e.alternate}else 20===e.type&&(e=e.value)}(e.codegenNode);r.alternate=_d(t,i+e.branches.length-1,n)}}}));function yd(e,t){const n=3===e.tagType;return{type:10,loc:e.loc,condition:"else"===t.name?void 0:t.exp,children:n&&!Qu(e,"for")?e.children:[e],userKey:Zu(e,"key"),isTemplateIf:n}}function _d(e,t,n){return e.condition?Tu(e.condition,bd(e,t,n),xu(n.helper(Va),['""',"true"])):bd(e,t,n)}function bd(e,t,n){const{helper:r}=n,o=_u("key",bu(`${t}`,!1,mu,2)),{children:s}=e,i=s[0];if(1!==s.length||1!==i.type){if(1===s.length&&11===i.type){const e=i.codegenNode;return af(e,o,n),e}{let t=64;return gu(n,r(Na),yu([o]),s,t,void 0,void 0,!0,!1,!1,e.loc)}}{const e=i.codegenNode,t=14===(c=e).type&&c.callee===du?c.arguments[1].returns:c;return 13===t.type&&wu(t,n),af(t,o,n),e}var c}const Sd=(e,t,n)=>{const{modifiers:r,loc:o}=e,s=e.arg;let{exp:i}=e;if(i&&4===i.type&&!i.content.trim()&&(i=void 0),!i){if(4!==s.type||!s.isStatic)return n.onError(Bu(52,s.loc)),{props:[_u(s,bu("",!0,o))]};xd(e),i=e.exp}return 4!==s.type?(s.children.unshift("("),s.children.push(') || ""')):s.isStatic||(s.content=s.content?`${s.content} || ""`:'""'),r.some(e=>"camel"===e.content)&&(4===s.type?s.isStatic?s.content=M(s.content):s.content=`${n.helperString(ru)}(${s.content})`:(s.children.unshift(`${n.helperString(ru)}(`),s.children.push(")"))),n.inSSR||(r.some(e=>"prop"===e.content)&&Cd(s,"."),r.some(e=>"attr"===e.content)&&Cd(s,"^")),{props:[_u(s,i)]}},xd=(e,t)=>{const n=e.arg,r=M(n.content);e.exp=bu(r,!1,n.loc)},Cd=(e,t)=>{4===e.type?e.isStatic?e.content=t+e.content:e.content=`\`${t}\${${e.content}}\``:(e.children.unshift(`'${t}' + (`),e.children.push(")"))},Td=id("for",(e,t,n)=>{const{helper:r,removeHelper:o}=n;return function(e,t,n,r){if(!t.exp)return void n.onError(Bu(31,t.loc));const o=t.forParseResult;if(!o)return void n.onError(Bu(32,t.loc));kd(o,n);const{addIdentifiers:s,removeIdentifiers:i,scopes:c}=n,{source:l,value:a,key:u,index:f}=o,d={type:11,loc:t.loc,source:l,valueAlias:a,keyAlias:u,objectIndexAlias:f,parseResult:o,children:of(e)?e.children:[e]};n.replaceNode(d),c.vFor++;const p=r&&r(d);return()=>{c.vFor--,p&&p()}}(e,t,n,t=>{const s=xu(r(Ka),[t.source]),i=of(e),c=Qu(e,"memo"),l=Zu(e,"key",!1,!0);l&&7===l.type&&!l.exp&&xd(l);let a=l&&(6===l.type?l.value?bu(l.value.content,!0):void 0:l.exp);const u=l&&a?_u("key",a):null,f=4===t.source.type&&t.source.constType>0,d=f?64:l?128:256;return t.codegenNode=gu(n,r(Na),void 0,s,d,void 0,void 0,!0,!f,!1,e.loc),()=>{let l;const{children:d}=t;const p=1!==d.length||1!==d[0].type,h=sf(e)?e:i&&1===e.children.length&&sf(e.children[0])?e.children[0]:null;if(h?(l=h.codegenNode,i&&u&&af(l,u,n)):p?l=gu(n,r(Na),u?yu([u]):void 0,e.children,64,void 0,void 0,!0,void 0,!1):(l=d[0].codegenNode,i&&u&&af(l,u,n),l.isBlock!==!f&&(l.isBlock?(o(Pa),o(Eu(n.inSSR,l.isComponent))):o(ku(n.inSSR,l.isComponent))),l.isBlock=!f,l.isBlock?(r(Pa),r(Eu(n.inSSR,l.isComponent))):r(ku(n.inSSR,l.isComponent))),c){const e=Cu(Ed(t.parseResult,[bu("_cached")]));e.body={type:21,body:[Su(["const _memo = (",c.exp,")"]),Su(["if (_cached",...a?[" && _cached.key === ",a]:[],` && ${n.helperString(pu)}(_cached, _memo)) return _cached`]),Su(["const _item = ",l]),bu("_item.memo = _memo"),bu("return _item")],loc:mu},s.arguments.push(e,bu("_cache"),bu(String(n.cached.length))),n.cached.push(null)}else s.arguments.push(Cu(Ed(t.parseResult),l,!0))}})});function kd(e,t){e.finalized||(e.finalized=!0)}function Ed({value:e,key:t,index:n},r=[]){return function(e){let t=e.length;for(;t--&&!e[t];);return e.slice(0,t+1).map((e,t)=>e||bu("_".repeat(t+1),!1))}([e,t,n,...r])}const wd=bu("undefined",!1),Ad=(e,t)=>{if(1===e.type&&(1===e.tagType||3===e.tagType)){const n=Qu(e,"slot");if(n)return n.exp,t.scopes.vSlot++,()=>{t.scopes.vSlot--}}},Nd=(e,t,n,r)=>Cu(e,n,!1,!0,n.length?n[0].loc:r);function Id(e,t,n=Nd){t.helper(au);const{children:r,loc:o}=e,s=[],i=[];let c=t.scopes.vSlot>0||t.scopes.vFor>0;const l=Qu(e,"slot",!0);if(l){const{arg:e,exp:t}=l;e&&!Uu(e)&&(c=!0),s.push(_u(e||bu("default",!0),n(t,void 0,r,o)))}let a=!1,u=!1;const f=[],d=new Set;let p=0;for(let e=0;e{const s=n(e,void 0,r,o);return t.compatConfig&&(s.isNonScopedSlot=!0),_u("default",s)};a?f.length&&f.some(e=>Md(e))&&(u?t.onError(Bu(39,f[0].loc)):s.push(e(void 0,f))):s.push(e(void 0,r))}const h=c?2:Od(e.children)?3:1;let m=yu(s.concat(_u("_",bu(h+"",!1))),o);return i.length&&(m=xu(t.helper(Ya),[m,vu(i)])),{slots:m,hasDynamicSlots:c}}function Rd(e,t,n){const r=[_u("name",e),_u("fn",t)];return null!=n&&r.push(_u("key",bu(String(n),!0))),yu(r)}function Od(e){for(let t=0;tfunction(){if(1!==(e=t.currentNode).type||0!==e.tagType&&1!==e.tagType)return;const{tag:n,props:r}=e,o=1===e.tagType;let s=o?function(e,t,n=!1){let{tag:r}=e;const o=Vd(r),s=Zu(e,"is",!1,!0);if(s)if(o||Lu("COMPILER_IS_ON_ELEMENT",t)){let e;if(6===s.type?e=s.value&&bu(s.value.content,!0):(e=s.exp,e||(e=bu("is",!1,s.arg.loc))),e)return xu(t.helper(ja),[e])}else 6===s.type&&s.value.content.startsWith("vue:")&&(r=s.value.content.slice(4));const i=Hu(r)||t.isBuiltInComponent(r);if(i)return n||t.helper(i),i;return t.helper(Ha),t.components.add(r),ff(r,"component")}(e,t):`"${n}"`;const i=x(s)&&s.callee===ja;let c,l,a,u,f,d=0,p=i||s===Ia||s===Ra||!o&&("svg"===n||"foreignObject"===n||"math"===n);if(r.length>0){const n=Ld(e,t,void 0,o,i);c=n.props,d=n.patchFlag,u=n.dynamicPropNames;const r=n.directives;f=r&&r.length?vu(r.map(e=>function(e,t){const n=[],r=Pd.get(e);r?n.push(t.helperString(r)):(t.helper(qa),t.directives.add(e.name),n.push(ff(e.name,"directive")));const{loc:o}=e;e.exp&&n.push(e.exp);e.arg&&(e.exp||n.push("void 0"),n.push(e.arg));if(Object.keys(e.modifiers).length){e.arg||(e.exp||n.push("void 0"),n.push("void 0"));const t=bu("true",!1,o);n.push(yu(e.modifiers.map(e=>_u(e,t)),o))}return vu(n,e.loc)}(e,t))):void 0,n.shouldUseBlock&&(p=!0)}if(e.children.length>0){s===Oa&&(p=!0,d|=1024);if(o&&s!==Ia&&s!==Oa){const{slots:n,hasDynamicSlots:r}=Id(e,t);l=n,r&&(d|=1024)}else if(1===e.children.length&&s!==Ia){const n=e.children[0],r=n.type,o=5===r||8===r;o&&0===Qf(n,t)&&(d|=1),l=o||2===r?n:e.children}else l=e.children}u&&u.length&&(a=function(e){let t="[";for(let n=0,r=e.length;n0;let h=!1,m=0,g=!1,v=!1,y=!1,_=!1,b=!1,x=!1;const C=[],T=e=>{u.length&&(f.push(yu($d(u),c)),u=[]),e&&f.push(e)},k=()=>{t.scopes.vFor>0&&u.push(_u(bu("ref_for",!0),bu("true")))},E=({key:e,value:n})=>{if(Uu(e)){const s=e.content,i=a(s);if(!i||r&&!o||"onclick"===s.toLowerCase()||"onUpdate:modelValue"===s||N(s)||(_=!0),i&&N(s)&&(x=!0),i&&14===n.type&&(n=n.arguments[0]),20===n.type||(4===n.type||8===n.type)&&Qf(n,t)>0)return;"ref"===s?g=!0:"class"===s?v=!0:"style"===s?y=!0:"key"===s||C.includes(s)||C.push(s),!r||"class"!==s&&"style"!==s||C.includes(s)||C.push(s)}else b=!0};for(let o=0;o"prop"===e.content)&&(m|=32);const x=t.directiveTransforms[n];if(x){const{props:n,needRuntime:r}=x(l,e,t);!s&&n.forEach(E),_&&o&&!Uu(o)?T(yu(n,c)):u.push(...n),r&&(d.push(l),S(r)&&Pd.set(l,r))}else I(n)||(d.push(l),p&&(h=!0))}}let w;if(f.length?(T(),w=f.length>1?xu(t.helper(Xa),f,c):f[0]):u.length&&(w=yu($d(u),c)),b?m|=16:(v&&!r&&(m|=2),y&&!r&&(m|=4),C.length&&(m|=8),_&&(m|=32)),h||0!==m&&32!==m||!(g||x||d.length>0)||(m|=512),!t.inSSR&&w)switch(w.type){case 15:let e=-1,n=-1,r=!1;for(let t=0;t{if(sf(e)){const{children:n,loc:r}=e,{slotName:o,slotProps:s}=function(e,t){let n,r='"default"';const o=[];for(let t=0;t0){const{props:r,directives:s}=Ld(e,t,o,!1,!1);n=r,s.length&&t.onError(Bu(36,s[0].loc))}return{slotName:r,slotProps:n}}(e,t),i=[t.prefixIdentifiers?"_ctx.$slots":"$slots",o,"{}","undefined","true"];let c=2;s&&(i[2]=s,c=3),n.length&&(i[3]=Cu([],n,!1,!1,r),c=4),t.scopeId&&!t.slotted&&(c=5),i.splice(c),e.codegenNode=xu(t.helper(Ja),i,r)}};const Ud=(e,t,n,r)=>{const{loc:o,modifiers:s,arg:i}=e;let c;if(e.exp||s.length||n.onError(Bu(35,o)),4===i.type)if(i.isStatic){let e=i.content;0,e.startsWith("vue:")&&(e=`vnode-${e.slice(4)}`);c=bu(0!==t.tagType||e.startsWith("vnode")||!/[A-Z]/.test(e)?$(M(e)):`on:${e}`,!0,i.loc)}else c=Su([`${n.helperString(su)}(`,i,")"]);else c=i,c.children.unshift(`${n.helperString(su)}(`),c.children.push(")");let l=e.exp;l&&!l.content.trim()&&(l=void 0);let a=n.cacheHandlers&&!l&&!n.inVOnce;if(l){const e=Yu(l),t=!(e||Xu(l)),n=l.content.includes(";");0,(t||a&&e)&&(l=Su([`${t?"$event":"(...args)"} => ${n?"{":"("}`,l,n?"}":")"]))}let u={props:[_u(c,l||bu("() => {}",!1,o))]};return r&&(u=r(u)),a&&(u.props[0].value=n.cache(u.props[0].value)),u.props.forEach(e=>e.key.isHandlerKey=!0),u},Hd=(e,t)=>{if(0===e.type||1===e.type||11===e.type||10===e.type)return()=>{const n=e.children;let r,o=!1;for(let e=0;e7===e.type&&!t.directiveTransforms[e.name])||"template"===e.tag)))for(let e=0;e{if(1===e.type&&Qu(e,"once",!0)){if(jd.has(e)||t.inVOnce||t.inSSR)return;return jd.add(e),t.inVOnce=!0,t.helper(iu),()=>{t.inVOnce=!1;const e=t.currentNode;e.codegenNode&&(e.codegenNode=t.cache(e.codegenNode,!0,!0))}}},Wd=(e,t,n)=>{const{exp:r,arg:o}=e;if(!r)return n.onError(Bu(41,e.loc)),zd();const s=r.loc.source.trim(),i=4===r.type?r.content:s,c=n.bindingMetadata[s];if("props"===c||"props-aliased"===c)return n.onError(Bu(44,r.loc)),zd();if(!i.trim()||!Yu(r))return n.onError(Bu(42,r.loc)),zd();const l=o||bu("modelValue",!0),a=o?Uu(o)?`onUpdate:${M(o.content)}`:Su(['"onUpdate:" + ',o]):"onUpdate:modelValue";let u;u=Su([`${n.isTS?"($event: any)":"$event"} => ((`,r,") = $event)"]);const f=[_u(l,e.exp),_u(a,u)];if(e.modifiers.length&&1===t.tagType){const t=e.modifiers.map(e=>e.content).map(e=>(qu(e)?e:JSON.stringify(e))+": true").join(", "),n=o?Uu(o)?`${o.content}Modifiers`:Su([o,' + "Modifiers"']):"modelModifiers";f.push(_u(n,bu(`{ ${t} }`,!1,e.loc,2)))}return zd(f)};function zd(e=[]){return{props:e}}const Kd=/[\w).+\-_$\]]/,Jd=(e,t)=>{Lu("COMPILER_FILTERS",t)&&(5===e.type?Yd(e.content,t):1===e.type&&e.props.forEach(e=>{7===e.type&&"for"!==e.name&&e.exp&&Yd(e.exp,t)}))};function Yd(e,t){if(4===e.type)Gd(e,t);else for(let n=0;n=0&&(e=n.charAt(t)," "===e);t--);e&&Kd.test(e)||(u=!0)}}else void 0===i?(h=s+1,i=n.slice(0,s).trim()):g();function g(){m.push(n.slice(h,s).trim()),h=s+1}if(void 0===i?i=n.slice(0,s).trim():0!==h&&g(),m.length){for(s=0;s{if(1===e.type){const n=Qu(e,"memo");if(!n||Qd.has(e))return;return Qd.add(e),()=>{const r=e.codegenNode||t.currentNode.codegenNode;r&&13===r.type&&(1!==e.tagType&&wu(r,t),e.codegenNode=xu(t.helper(du),[n.exp,Cu(void 0,r),"_cache",String(t.cached.length)]),t.cached.push(null))}}};function ep(e,t={}){const n=t.onError||Fu,r="module"===t.mode;!0===t.prefixIdentifiers?n(Bu(47)):r&&n(Bu(48));t.cacheHandlers&&n(Bu(49)),t.scopeId&&!r&&n(Bu(50));const o=f({},t,{prefixIdentifiers:!1}),s=b(e)?Jf(e,o):e,[i,c]=[[qd,vd,Zd,Td,Jd,Bd,Dd,Ad,Hd],{on:Ud,bind:Sd,model:Wd}];return od(s,f({},o,{nodeTransforms:[...i,...t.nodeTransforms||[]],directiveTransforms:f({},c,t.directiveTransforms||{})})),ad(s,o)}const tp=Symbol(""),np=Symbol(""),rp=Symbol(""),op=Symbol(""),sp=Symbol(""),ip=Symbol(""),cp=Symbol(""),lp=Symbol(""),ap=Symbol(""),up=Symbol("");var fp;let dp;fp={[tp]:"vModelRadio",[np]:"vModelCheckbox",[rp]:"vModelText",[op]:"vModelSelect",[sp]:"vModelDynamic",[ip]:"withModifiers",[cp]:"withKeys",[lp]:"vShow",[ap]:"Transition",[up]:"TransitionGroup"},Object.getOwnPropertySymbols(fp).forEach(e=>{hu[e]=fp[e]});const pp={parseMode:"html",isVoidTag:ne,isNativeTag:e=>Z(e)||ee(e)||te(e),isPreTag:e=>"pre"===e,isIgnoreNewlineTag:e=>"pre"===e||"textarea"===e,decodeEntities:function(e,t=!1){return dp||(dp=document.createElement("div")),t?(dp.innerHTML=`
`,dp.children[0].getAttribute("foo")):(dp.innerHTML=e,dp.textContent)},isBuiltInComponent:e=>"Transition"===e||"transition"===e?ap:"TransitionGroup"===e||"transition-group"===e?up:void 0,getNamespace(e,t,n){let r=t?t.ns:n;if(t&&2===r)if("annotation-xml"===t.tag){if("svg"===e)return 1;t.props.some(e=>6===e.type&&"encoding"===e.name&&null!=e.value&&("text/html"===e.value.content||"application/xhtml+xml"===e.value.content))&&(r=0)}else/^m(?:[ions]|text)$/.test(t.tag)&&"mglyph"!==e&&"malignmark"!==e&&(r=0);else t&&1===r&&("foreignObject"!==t.tag&&"desc"!==t.tag&&"title"!==t.tag||(r=0));if(0===r){if("svg"===e)return 1;if("math"===e)return 2}return r}},hp=(e,t)=>{const n=G(e);return bu(JSON.stringify(n),!1,t,3)};function mp(e,t){return Bu(e,t)}const gp=o("passive,once,capture"),vp=o("stop,prevent,self,ctrl,shift,alt,meta,exact,middle"),yp=o("left,right"),_p=o("onkeyup,onkeydown,onkeypress"),bp=(e,t)=>Uu(e)&&"onclick"===e.content.toLowerCase()?bu(t,!0):4!==e.type?Su(["(",e,`) === "onClick" ? "${t}" : (`,e,")"]):e;const Sp=(e,t)=>{1!==e.type||0!==e.tagType||"script"!==e.tag&&"style"!==e.tag||t.removeNode()};const xp=[e=>{1===e.type&&e.props.forEach((t,n)=>{6===t.type&&"style"===t.name&&t.value&&(e.props[n]={type:7,name:"bind",arg:bu("style",!0,t.loc),exp:hp(t.value.content,t.loc),modifiers:[],loc:t.loc})})}],Cp={cloak:()=>({props:[]}),html:(e,t,n)=>{const{exp:r,loc:o}=e;return r||n.onError(mp(53,o)),t.children.length&&(n.onError(mp(54,o)),t.children.length=0),{props:[_u(bu("innerHTML",!0,o),r||bu("",!0))]}},text:(e,t,n)=>{const{exp:r,loc:o}=e;return r||n.onError(mp(55,o)),t.children.length&&(n.onError(mp(56,o)),t.children.length=0),{props:[_u(bu("textContent",!0),r?Qf(r,n)>0?r:xu(n.helperString(Ga),[r],o):bu("",!0))]}},model:(e,t,n)=>{const r=Wd(e,t,n);if(!r.props.length||1===t.tagType)return r;e.arg&&n.onError(mp(58,e.arg.loc));const{tag:o}=t,s=n.isCustomElement(o);if("input"===o||"textarea"===o||"select"===o||s){let i=rp,c=!1;if("input"===o||s){const r=Zu(t,"type");if(r){if(7===r.type)i=sp;else if(r.value)switch(r.value.content){case"radio":i=tp;break;case"checkbox":i=np;break;case"file":c=!0,n.onError(mp(59,e.loc))}}else(function(e){return e.props.some(e=>!(7!==e.type||"bind"!==e.name||e.arg&&4===e.arg.type&&e.arg.isStatic))})(t)&&(i=sp)}else"select"===o&&(i=op);c||(r.needRuntime=n.helper(i))}else n.onError(mp(57,e.loc));return r.props=r.props.filter(e=>!(4===e.key.type&&"modelValue"===e.key.content)),r},on:(e,t,n)=>Ud(e,t,n,t=>{const{modifiers:r}=e;if(!r.length)return t;let{key:o,value:s}=t.props[0];const{keyModifiers:i,nonKeyModifiers:c,eventOptionModifiers:l}=((e,t,n)=>{const r=[],o=[],s=[];for(let i=0;i{const{exp:r,loc:o}=e;return r||n.onError(mp(61,o)),{props:[],needRuntime:n.helper(lp)}}};const Tp=Object.create(null);function kp(e,t){if(!b(e)){if(!e.nodeType)return c;e=e.innerHTML}const n=function(e,t){return e+JSON.stringify(t,(e,t)=>"function"==typeof t?t.toString():t)}(e,t),o=Tp[n];if(o)return o;if("#"===e[0]){const t=document.querySelector(e);0,e=t?t.innerHTML:""}const s=f({hoistStatic:!0,onError:void 0,onWarn:c},t);s.isCustomElement||"undefined"==typeof customElements||(s.isCustomElement=e=>!!customElements.get(e));const{code:i}=function(e,t={}){return ep(e,f({},pp,t,{nodeTransforms:[Sp,...xp,...t.nodeTransforms||[]],directiveTransforms:f({},Cp,t.directiveTransforms||{}),transformHoist:null}))}(e,s);const l=new Function("Vue",i)(r);return l._rc=!0,Tp[n]=l}hc(kp)},171:function(e,t,n){n.d(t,{M:function(){return r}});var r=function(e,t){void 0===t&&(t=["event"]);var n=e.startsWith("$")?function(){return window.$(document).trigger(e.slice(1),[].slice.call(arguments)[0].detail)}:function(){var n=arguments,r=t.reduce(function(e,t,r){return e[t]=[].slice.call(n)[r],e},{});r.event.target.dispatchEvent(new CustomEvent("$"+e,{detail:r,bubbles:!0,cancelable:!0}))};return e.startsWith("$")?document.addEventListener(e,n):window.$(document).on(e,n),n}},433:function(e,t){t.A=(e,t)=>{const n=e.__vccOpts||e;for(const[e,r]of t)n[e]=r;return n}},591:function(e,t,n){var r,o=function(){return void 0===r&&(r=Boolean(window&&document&&document.all&&!window.atob)),r},s=function(){var e={};return function(t){if(void 0===e[t]){var n=document.querySelector(t);if(window.HTMLIFrameElement&&n instanceof window.HTMLIFrameElement)try{n=n.contentDocument.head}catch(e){n=null}e[t]=n}return e[t]}}(),i=[];function c(e){for(var t=-1,n=0;n { + Snowboard.addPlugin('backend.ajax.handler', BackendAjaxHandler); + Snowboard.addPlugin('backend.ui.eventHandler', BackendUiEventHandler); + Snowboard.addPlugin('backend.ui.widgetHandler', BackendUiWidgetHandler); + + // Add the pre-filter immediately + Snowboard['backend.ajax.handler']().addPrefilter(); + + // Add polyfill for AssetManager + window.AssetManager = { + load: (assets, callback) => { + Snowboard.assetLoader().load(assets).then( + () => { + if (callback && typeof callback === 'function') { + callback(); + } + }, + ); + }, + }; + window.assetManager = window.AssetManager; +})(window.Snowboard); + +// Add Vue to global scope +window.Vue = Vue; diff --git a/modules/backend/assets/ui/js/pages/Preferences.js b/modules/backend/assets/ui/js/pages/Preferences.js new file mode 100644 index 0000000..85378a2 --- /dev/null +++ b/modules/backend/assets/ui/js/pages/Preferences.js @@ -0,0 +1,100 @@ +import { delegate } from 'jquery-events-to-dom-events'; + +((Snowboard) => { + class Preferences extends Snowboard.Singleton { + construct() { + this.widget = null; + } + + listens() { + return { + 'backend.widget.initialized': 'onWidgetInitialized', + }; + } + + onWidgetInitialized(element, widget) { + if (element === document.getElementById('CodeEditor-formEditorPreview-_editor_preview')) { + this.widget = widget; + this.enablePreferences(); + } + } + + enablePreferences() { + delegate('change'); + + const checkboxes = { + show_gutter: 'showGutter', + highlight_active_line: 'highlightActiveLine', + use_hard_tabs: '!useSoftTabs', + display_indent_guides: 'displayIndentGuides', + show_invisibles: 'showInvisibles', + show_print_margin: 'showPrintMargin', + show_minimap: 'showMinimap', + enable_folding: 'codeFolding', + bracket_colors: 'bracketColors', + show_colors: 'showColors', + }; + + Object.entries(checkboxes).forEach(([key, value]) => { + this.element(key).addEventListener('change', (event) => { + this.widget.setConfig( + value.replace(/^!/, ''), + /^!/.test(value) ? !event.target.checked : event.target.checked, + ); + }); + }); + + this.element('theme').addEventListener('$change', (event) => { + this.widget.loadTheme(event.target.value); + }); + + this.element('font_size').addEventListener('$change', (event) => { + this.widget.setConfig('fontSize', event.target.value); + }); + + this.element('tab_size').addEventListener('$change', (event) => { + this.widget.setConfig('tabSize', event.target.value); + }); + + this.element('word_wrap').addEventListener('$change', (event) => { + const { value } = event.target; + switch (value) { + case 'off': + this.widget.setConfig('wordWrap', false); + break; + case 'fluid': + this.widget.setConfig('wordWrap', 'fluid'); + break; + default: + this.widget.setConfig('wordWrap', parseInt(value, 10)); + } + }); + + document.querySelectorAll('[data-switch-lang]').forEach((element) => { + element.addEventListener('click', (event) => { + event.preventDefault(); + const language = element.dataset.switchLang; + const template = document.querySelector(`[data-lang-snippet="${language}"]`); + + if (!template) { + return; + } + + this.widget.setValue(template.textContent.trim()); + this.widget.setLanguage(language); + }); + }); + + this.widget.events.once('create', () => { + const event = new MouseEvent('click'); + document.querySelector('[data-switch-lang="css"]').dispatchEvent(event); + }); + } + + element(key) { + return document.getElementById(`Form-field-Preference-editor_${key}`); + } + } + + Snowboard.addPlugin('backend.preferences', Preferences); +})(window.Snowboard); diff --git a/modules/backend/assets/ui/js/ui/EventHandler.js b/modules/backend/assets/ui/js/ui/EventHandler.js new file mode 100644 index 0000000..1bc70cd --- /dev/null +++ b/modules/backend/assets/ui/js/ui/EventHandler.js @@ -0,0 +1,116 @@ +/** + * Widget event handler. + * + * Extends a widget with event handling functionality, allowing for the quick definition of events + * and listening for events on a specific instance of a widget. + * + * This is a complement to Snowboard's global events - these events will still fire in order to + * allow external code to listen and handle events. Local events can cancel the global event (and + * further local events) by returning `false` from the callback. + * + * @copyright 2022 Winter. + * @author Ben Thomson + */ +export default class EventHandler extends Snowboard.PluginBase { + /** + * Constructor. + * + * @param {PluginBase} instance + * @param {String} eventPrefix + */ + construct(instance, eventPrefix) { + if (instance instanceof Snowboard.PluginBase === false) { + throw new Error('Event handling can only be applied to Snowboard classes.'); + } + if (!eventPrefix) { + throw new Error('Event prefix is required.'); + } + this.instance = instance; + this.eventPrefix = eventPrefix; + this.events = []; + } + + /** + * Registers a listener for a widget's event. + * + * @param {String} event + * @param {Function} callback + */ + on(event, callback) { + this.events.push({ + event, + callback, + }); + } + + /** + * Deregisters a listener for a widget's event. + * + * @param {String} event + * @param {Function} callback + */ + off(event, callback) { + this.events = this.events.filter((registeredEvent) => registeredEvent.event !== event || registeredEvent.callback !== callback); + } + + /** + * Registers a listener for a widget's event that will only fire once. + * + * @param {String} event + * @param {Function} callback + */ + once(event, callback) { + const length = this.events.push({ + event, + callback: (...parameters) => { + callback(...parameters); + this.events.splice(length - 1, 1); + }, + }); + } + + /** + * Fires an event on the widget. + * + * Local events are fired first, then a global event is fired afterwards. + * + * @param {String} eventName + * @param {...any} parameters + */ + fire(eventName, ...parameters) { + // Fire local events first + const events = this.events.filter((registeredEvent) => registeredEvent.event === eventName); + let cancelled = false; + events.forEach((event) => { + if (cancelled) { + return; + } + if (event.callback(...parameters) === false) { + cancelled = true; + } + }); + + if (!cancelled) { + this.snowboard.globalEvent(`${this.eventPrefix}.${eventName}`, ...parameters); + } + } + + /** + * Fires a promise event on the widget. + * + * Local events are fired first, then a global event is fired afterwards. + * + * @param {String} eventName + * @param {...any} parameters + */ + firePromise(eventName, ...parameters) { + const events = this.events.filter((registeredEvent) => registeredEvent.event === eventName); + const promises = events.filter((event) => event !== null, events.map((event) => event.callback(...parameters))); + + Promise.all(promises).then( + () => { + this.snowboard.globalPromiseEvent(`${this.eventPrefix}.${eventName}`, ...parameters); + }, + ); + } +} diff --git a/modules/backend/assets/ui/js/ui/WidgetHandler.js b/modules/backend/assets/ui/js/ui/WidgetHandler.js new file mode 100644 index 0000000..f332b55 --- /dev/null +++ b/modules/backend/assets/ui/js/ui/WidgetHandler.js @@ -0,0 +1,181 @@ +/** + * Backend widget handler. + * + * Handles the creation and disposal of widgets in the Backend. Widgets should include this as + * a dependency in order to be loaded and initialised after the handler, in order to correctly + * register. + * + * @copyright 2022 Winter. + * @author Ben Thomson + */ +export default class WidgetHandler extends Snowboard.Singleton { + /** + * Constructor. + */ + construct() { + this.registeredWidgets = []; + this.elements = []; + this.events = { + mutate: (mutations) => this.onMutation(mutations), + }; + this.observer = null; + } + + /** + * Listeners. + * + * @returns {Object} + */ + listens() { + return { + ready: 'onReady', + render: 'onRender', + ajaxUpdate: 'onAjaxUpdate', + }; + } + + /** + * Registers a widget as a given data control. + * + * Registering a widget will allow any element that contains a "data-control" attribute matching + * the control name to be initialized with the given widget. + * + * You may optionally provide a callback that will be fired when an instance of the widget is + * initialized - the callback will be provided the element and the widget instance as parameters. + * + * @param {String} control + * @param {Snowboard.PluginBase} widget + * @param {Function} callback + */ + register(control, widget, callback) { + this.registeredWidgets.push({ + control, + widget, + callback, + }); + } + + /** + * Unregisters a data control. + * + * @param {String} control + */ + unregister(control) { + this.registeredWidgets = this.registeredWidgets.filter((widget) => widget.control !== control); + } + + /** + * Ready handler. + * + * Initializes widgets within the entire document. + */ + onReady() { + this.initializeWidgets(document.body); + + // Register a DOM observer and watch for any removed nodes + if (!this.observer) { + this.observer = new MutationObserver(this.events.mutate); + this.observer.observe(document.body, { + childList: true, + subtree: true, + }); + } + } + + /** + * Render handler. + * + * Initializes widgets within the entire document. + */ + onRender() { + this.initializeWidgets(document.body); + } + + /** + * AJAX update handler. + * + * Initializes widgets inside an update element from an AJAX response. + * + * @param {HTMLElement} element + */ + onAjaxUpdate(element) { + this.initializeWidgets(element); + } + + /** + * Initializes all widgets within an element. + * + * If an element contains a "data-control" attribute matching a registered widget, the widget + * is initialized and attached to the element as a "widget" property. + * + * Only one widget may be initialized to a particular element. + * + * @param {HTMLElement} element + */ + initializeWidgets(element) { + this.registeredWidgets.forEach((widget) => { + const instances = element.querySelectorAll(`[data-control="${widget.control}"]:not([data-widget-initialized])`); + + if (instances.length) { + instances.forEach((instance) => { + // Prevent double-widget initialization + if (instance.dataset.widgetInitialized) { + return; + } + + const widgetInstance = this.snowboard[widget.widget](instance); + this.elements.push({ + element: instance, + instance: widgetInstance, + }); + instance.dataset.widgetInitialized = true; + this.snowboard.globalEvent('backend.widget.initialized', instance, widgetInstance); + + if (typeof widget.callback === 'function') { + widget.callback(widgetInstance, instance); + } + }); + } + }); + } + + /** + * Returns a widget that is attached to the given element, if any. + * + * @param {HTMLElement} element + * @returns {Snowboard.PluginBase|null} + */ + getWidget(element) { + const found = this.elements.find((widget) => widget.element === element); + + if (found) { + return found.instance; + } + + return null; + } + + /** + * Callback for mutation events. + * + * We're only tracking removed nodes, to ensure that those widgets are disposed of. + * + * @param {MutationRecord[]} mutations + */ + onMutation(mutations) { + const removedNodes = mutations.filter((mutation) => mutation.removedNodes.length).map((mutation) => Array.from(mutation.removedNodes)).flat(); + if (!removedNodes.length) { + return; + } + + removedNodes.forEach((node) => { + const widgets = this.elements.filter((widget) => node.contains(widget.element)); + if (widgets.length) { + widgets.forEach((widget) => { + widget.instance.destruct(); + this.elements = this.elements.filter((element) => element !== widget); + }); + } + }); + } +} diff --git a/modules/backend/assets/vendor/ace-codeeditor/build-min.js b/modules/backend/assets/vendor/ace-codeeditor/build-min.js new file mode 100644 index 0000000..c22c2f7 --- /dev/null +++ b/modules/backend/assets/vendor/ace-codeeditor/build-min.js @@ -0,0 +1,2314 @@ +var _=(function(){var root=this;var previousUnderscore=root._;var breaker={};var ArrayProto=Array.prototype,ObjProto=Object.prototype,FuncProto=Function.prototype;var slice=ArrayProto.slice,unshift=ArrayProto.unshift,toString=ObjProto.toString,hasOwnProperty=ObjProto.hasOwnProperty;var nativeForEach=ArrayProto.forEach,nativeMap=ArrayProto.map,nativeReduce=ArrayProto.reduce,nativeReduceRight=ArrayProto.reduceRight,nativeFilter=ArrayProto.filter,nativeEvery=ArrayProto.every,nativeSome=ArrayProto.some,nativeIndexOf=ArrayProto.indexOf,nativeLastIndexOf=ArrayProto.lastIndexOf,nativeIsArray=Array.isArray,nativeKeys=Object.keys,nativeBind=FuncProto.bind;var _=function(obj){return new wrapper(obj);};if(typeof exports!=='undefined'){if(typeof module!=='undefined'&&module.exports){exports=module.exports=_;}exports._=_;}else{root['_']=_;}_.VERSION='1.3.3';var each=_.each=_.forEach=function(obj,iterator,context){if(obj==null)return;if(nativeForEach&&obj.forEach===nativeForEach){obj.forEach(iterator,context); +}else if(obj.length===+obj.length){for(var i=0,l=obj.length;i2;if(obj==null)obj=[];if(nativeReduce&&obj.reduce===nativeReduce){if(context)iterator=_.bind(iterator,context);return initial?obj.reduce(iterator,memo):obj.reduce(iterator);}each(obj,function(value,index,list){if(!initial){memo=value;initial=true;}else{memo=iterator.call(context,memo,value,index,list);}});if(!initial)throw new TypeError('Reduce of empty array with no initial value'); +return memo;};_.reduceRight=_.foldr=function(obj,iterator,memo,context){var initial=arguments.length>2;if(obj==null)obj=[];if(nativeReduceRight&&obj.reduceRight===nativeReduceRight){if(context)iterator=_.bind(iterator,context);return initial?obj.reduceRight(iterator,memo):obj.reduceRight(iterator);}var reversed=_.toArray(obj).reverse();if(context&&!initial)iterator=_.bind(iterator,context);return initial?_.reduce(reversed,iterator,memo,context):_.reduce(reversed,iterator);};_.find=_.detect=function(obj,iterator,context){var result;any(obj,function(value,index,list){if(iterator.call(context,value,index,list)){result=value;return true;}});return result;};_.filter=_.select=function(obj,iterator,context){var results=[];if(obj==null)return results;if(nativeFilter&&obj.filter===nativeFilter)return obj.filter(iterator,context);each(obj,function(value,index,list){if(iterator.call(context,value,index,list))results[results.length]=value;});return results;};_.reject=function(obj,iterator,context){ +var results=[];if(obj==null)return results;each(obj,function(value,index,list){if(!iterator.call(context,value,index,list))results[results.length]=value;});return results;};_.every=_.all=function(obj,iterator,context){var result=true;if(obj==null)return result;if(nativeEvery&&obj.every===nativeEvery)return obj.every(iterator,context);each(obj,function(value,index,list){if(!(result=result&&iterator.call(context,value,index,list)))return breaker;});return!!result;};var any=_.some=_.any=function(obj,iterator,context){iterator||(iterator=_.identity);var result=false;if(obj==null)return result;if(nativeSome&&obj.some===nativeSome)return obj.some(iterator,context);each(obj,function(value,index,list){if(result||(result=iterator.call(context,value,index,list)))return breaker;});return!!result;};_.include=_.contains=function(obj,target){var found=false;if(obj==null)return found;if(nativeIndexOf&&obj.indexOf===nativeIndexOf)return obj.indexOf(target)!=-1;found=any(obj,function(value){return value===target; +});return found;};_.invoke=function(obj,method){var args=slice.call(arguments,2);return _.map(obj,function(value){return(_.isFunction(method)?method||value:value[method]).apply(value,args);});};_.pluck=function(obj,key){return _.map(obj,function(value){return value[key];});};_.max=function(obj,iterator,context){if(!iterator&&_.isArray(obj)&&obj[0]===+obj[0])return Math.max.apply(Math,obj);if(!iterator&&_.isEmpty(obj))return-Infinity;var result={computed:-Infinity};each(obj,function(value,index,list){var computed=iterator?iterator.call(context,value,index,list):value;computed>=result.computed&&(result={value:value,computed:computed});});return result.value;};_.min=function(obj,iterator,context){if(!iterator&&_.isArray(obj)&&obj[0]===+obj[0])return Math.min.apply(Math,obj);if(!iterator&&_.isEmpty(obj))return Infinity;var result={computed:Infinity};each(obj,function(value,index,list){var computed=iterator?iterator.call(context,value,index,list):value;computedb?1:0;}),'value');};_.groupBy=function(obj,val){var result={};var iterator=_.isFunction(val)?val:function(obj){return obj[val];};each(obj,function(value,index){var key=iterator(value,index);(result[key]||(result[key]=[])).push(value);});return result;};_.sortedIndex=function(array,obj,iterator){iterator||(iterator=_.identity);var low=0,high=array.length;while(low>1;iterator(array[mid])=0;});});};_.difference=function(array){var rest=_.flatten(slice.call(arguments,1),true);return _.filter(array,function(value){return!_.include(rest,value);});};_.zip=function(){var args=slice.call(arguments);var length=_.max(_.pluck(args,'length'));var results=new Array(length);for(var i=0;i=0;i--){args=[funcs[i].apply(this,args)];}return args[0];};};_.after=function(times,func){ +if(times<=0)return func();return function(){if(--times<1){return func.apply(this,arguments);}};};_.keys=nativeKeys||function(obj){if(obj!==Object(obj))throw new TypeError('Invalid object');var keys=[];for(var key in obj)if(_.has(obj,key))keys[keys.length]=key;return keys;};_.values=function(obj){return _.map(obj,_.identity);};_.functions=_.methods=function(obj){var names=[];for(var key in obj){if(_.isFunction(obj[key]))names.push(key);}return names.sort();};_.extend=function(obj){each(slice.call(arguments,1),function(source){for(var prop in source){obj[prop]=source[prop];}});return obj;};_.pick=function(obj){var result={};each(_.flatten(slice.call(arguments,1)),function(key){if(key in obj)result[key]=obj[key];});return result;};_.defaults=function(obj){each(slice.call(arguments,1),function(source){for(var prop in source){if(obj[prop]==null)obj[prop]=source[prop];}});return obj;};_.clone=function(obj){if(!_.isObject(obj))return obj;return _.isArray(obj)?obj.slice():_.extend({},obj);};_.tap=function(obj,interceptor){ +interceptor(obj);return obj;};function eq(a,b,stack){if(a===b)return a!==0||1/a==1/b;if(a==null||b==null)return a===b;if(a._chain)a=a._wrapped;if(b._chain)b=b._wrapped;if(a.isEqual&&_.isFunction(a.isEqual))return a.isEqual(b);if(b.isEqual&&_.isFunction(b.isEqual))return b.isEqual(a);var className=toString.call(a);if(className!=toString.call(b))return false;switch(className){case'[object String]':return a==String(b);case'[object Number]':return a!=+a?b!=+b:(a==0?1/a==1/b:a==+b);case'[object Date]':case'[object Boolean]':return+a==+b;case'[object RegExp]':return a.source==b.source&&a.global==b.global&&a.multiline==b.multiline&&a.ignoreCase==b.ignoreCase;}if(typeof a!='object'||typeof b!='object')return false;var length=stack.length;while(length--){if(stack[length]==a)return true;}stack.push(a);var size=0,result=true;if(className=='[object Array]'){size=a.length;result=size==b.length;if(result){while(size--){if(!(result=size in a==size in b&&eq(a[size],b[size],stack)))break;}}}else{if('constructor'in a!='constructor'in b||a.constructor!=b.constructor)return false; +for(var key in a){if(_.has(a,key)){size++;if(!(result=_.has(b,key)&&eq(a[key],b[key],stack)))break;}}if(result){for(key in b){if(_.has(b,key)&&!(size--))break;}result=!size;}}stack.pop();return result;}_.isEqual=function(a,b){return eq(a,b,[]);};_.isEmpty=function(obj){if(obj==null)return true;if(_.isArray(obj)||_.isString(obj))return obj.length===0;for(var key in obj)if(_.has(obj,key))return false;return true;};_.isElement=function(obj){return!!(obj&&obj.nodeType==1);};_.isArray=nativeIsArray||function(obj){return toString.call(obj)=='[object Array]';};_.isObject=function(obj){return obj===Object(obj);};_.isArguments=function(obj){return toString.call(obj)=='[object Arguments]';};if(!_.isArguments(arguments)){_.isArguments=function(obj){return!!(obj&&_.has(obj,'callee'));};}_.isFunction=function(obj){return toString.call(obj)=='[object Function]';};_.isString=function(obj){return toString.call(obj)=='[object String]';};_.isNumber=function(obj){return toString.call(obj)=='[object Number]'; +};_.isFinite=function(obj){return _.isNumber(obj)&&isFinite(obj);};_.isNaN=function(obj){return obj!==obj;};_.isBoolean=function(obj){return obj===true||obj===false||toString.call(obj)=='[object Boolean]';};_.isDate=function(obj){return toString.call(obj)=='[object Date]';};_.isRegExp=function(obj){return toString.call(obj)=='[object RegExp]';};_.isNull=function(obj){return obj===null;};_.isUndefined=function(obj){return obj===void 0;};_.has=function(obj,key){return hasOwnProperty.call(obj,key);};_.noConflict=function(){root._=previousUnderscore;return this;};_.identity=function(value){return value;};_.times=function(n,iterator,context){for(var i=0;i/g,'>').replace(/"/g,'"').replace(/'/g,''').replace(/\//g,'/');};_.result=function(object,property){if(object==null)return null;var value=object[property];return _.isFunction(value)?value.call(object):value; +};_.mixin=function(obj){each(_.functions(obj),function(name){addToWrapper(name,_[name]=obj[name]);});};var idCounter=0;_.uniqueId=function(prefix){var id=idCounter++;return prefix?prefix+id:id;};_.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var noMatch=/.^/;var escapes={'\\':'\\',"'":"'",'r':'\r','n':'\n','t':'\t','u2028':'\u2028','u2029':'\u2029'};for(var p in escapes)escapes[escapes[p]]=p;var escaper=/\\|'|\r|\n|\t|\u2028|\u2029/g;var unescaper=/\\(\\|'|r|n|t|u2028|u2029)/g;var unescape=function(code){return code.replace(unescaper,function(match,escape){return escapes[escape];});};_.template=function(text,data,settings){settings=_.defaults(settings||{},_.templateSettings);var source="__p+='"+text.replace(escaper,function(match){return'\\'+escapes[match];}).replace(settings.escape||noMatch,function(match,code){return"'+\n_.escape("+unescape(code)+")+\n'";}).replace(settings.interpolate||noMatch,function(match,code){return"'+\n("+unescape(code)+")+\n'"; +}).replace(settings.evaluate||noMatch,function(match,code){return"';\n"+unescape(code)+"\n;__p+='";})+"';\n";if(!settings.variable)source='with(obj||{}){\n'+source+'}\n';source="var __p='';"+"var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n"+source+"return __p;\n";var render=new Function(settings.variable||'obj','_',source);if(data)return render(data,_);var template=function(data){return render.call(this,data,_);};template.source='function('+(settings.variable||'obj')+'){\n'+source+'}';return template;};_.chain=function(obj){return _(obj).chain();};var wrapper=function(obj){this._wrapped=obj;};_.prototype=wrapper.prototype;var result=function(obj,chain){return chain?_(obj).chain():obj;};var addToWrapper=function(name,func){wrapper.prototype[name]=function(){var args=slice.call(arguments);unshift.call(args,this._wrapped);return result(func.apply(_,args),this._chain);};};_.mixin(_);each(['pop','push','reverse','shift','sort','splice','unshift'],function(name){var method=ArrayProto[name]; +wrapper.prototype[name]=function(){var wrapped=this._wrapped;method.apply(wrapped,arguments);var length=wrapped.length;if((name=='shift'||name=='splice')&&length===0)delete wrapped[0];return result(wrapped,this._chain);};});each(['concat','join','slice'],function(name){var method=ArrayProto[name];wrapper.prototype[name]=function(){return result(method.apply(this._wrapped,arguments),this._chain);};});wrapper.prototype.chain=function(){this._chain=true;return this;};wrapper.prototype.value=function(){return this._wrapped;};return _;}).call({});var emmet=(function(global){var defaultSyntax='html';var defaultProfile='plain';if(typeof _=='undefined'){try{_=global[['require'][0]]('underscore');}catch(e){}}if(typeof _=='undefined'){throw'Cannot access to Underscore.js lib';}var modules={_:_};var ctor=function(){};function inherits(parent,protoProps,staticProps){var child;if(protoProps&&protoProps.hasOwnProperty('constructor')){child=protoProps.constructor;}else{child=function(){parent.apply(this,arguments); +};}_.extend(child,parent);ctor.prototype=parent.prototype;child.prototype=new ctor();if(protoProps)_.extend(child.prototype,protoProps);if(staticProps)_.extend(child,staticProps);child.prototype.constructor=child;child.__super__=parent.prototype;return child;};var moduleLoader=null;function r(name){if(!(name in modules)&&moduleLoader)moduleLoader(name);return modules[name];}return{define:function(name,factory){if(!(name in modules)){modules[name]=_.isFunction(factory)?this.exec(factory):factory;}},require:r,exec:function(fn,context){return fn.call(context||global,_.bind(r,this),_,this);},extend:function(protoProps,classProps){var child=inherits(this,protoProps,classProps);child.extend=this.extend;if(protoProps.hasOwnProperty('toString'))child.prototype.toString=protoProps.toString;return child;},expandAbbreviation:function(abbr,syntax,profile,contextNode){if(!abbr)return'';syntax=syntax||defaultSyntax;var filters=r('filters');var parser=r('abbreviationParser');profile=r('profile').get(profile,syntax); +r('tabStops').resetTabstopIndex();var data=filters.extractFromAbbreviation(abbr);var outputTree=parser.parse(data[0],{syntax:syntax,contextNode:contextNode});var filtersList=filters.composeList(syntax,profile,data[1]);filters.apply(outputTree,filtersList,profile);return outputTree.toString();},defaultSyntax:function(){return defaultSyntax;},defaultProfile:function(){return defaultProfile;},log:function(){if(global.console&&global.console.log)global.console.log.apply(global.console,arguments);},setModuleLoader:function(fn){moduleLoader=fn;}};})(this);if(typeof exports!=='undefined'){if(typeof module!=='undefined'&&module.exports){exports=module.exports=emmet;}exports.emmet=emmet;}if(typeof define!=='undefined'){define('emmet',[],emmet);}emmet.define('abbreviationParser',function(require,_){var reValidName=/^[\w\-\$\:@\!%]+\+?$/i;var reWord=/[\w\-:\$@]/;var pairs={'[':']','(':')','{':'}'};var spliceFn=Array.prototype.splice;var preprocessors=[];var postprocessors=[];var outputProcessors=[]; +function AbbreviationNode(parent){this.parent=null;this.children=[];this._attributes=[];this.abbreviation='';this.counter=1;this._name=null;this._text='';this.repeatCount=1;this.hasImplicitRepeat=false;this._data={};this.start='';this.end='';this.content='';this.padding='';}AbbreviationNode.prototype={addChild:function(child,position){child=child||new AbbreviationNode;child.parent=this;if(_.isUndefined(position)){this.children.push(child);}else{this.children.splice(position,0,child);}return child;},clone:function(){var node=new AbbreviationNode();var attrs=['abbreviation','counter','_name','_text','repeatCount','hasImplicitRepeat','start','end','content','padding'];_.each(attrs,function(a){node[a]=this[a];},this);node._attributes=_.map(this._attributes,function(attr){return _.clone(attr);});node._data=_.clone(this._data);node.children=_.map(this.children,function(child){child=child.clone();child.parent=node;return child;});return node;},remove:function(){if(this.parent){this.parent.children=_.without(this.parent.children,this); +}return this;},replace:function(){var parent=this.parent;var ix=_.indexOf(parent.children,this);var items=_.flatten(arguments);spliceFn.apply(parent.children,[ix,1].concat(items));_.each(items,function(item){item.parent=parent;});},updateProperty:function(name,value){this[name]=value;_.each(this.children,function(child){child.updateProperty(name,value);});return this;},find:function(fn){return this.findAll(fn)[0];},findAll:function(fn){if(!_.isFunction(fn)){var elemName=fn.toLowerCase();fn=function(item){return item.name().toLowerCase()==elemName;};}var result=[];_.each(this.children,function(child){if(fn(child))result.push(child);result=result.concat(child.findAll(fn));});return _.compact(result);},data:function(name,value){if(arguments.length==2){this._data[name]=value;if(name=='resource'&&require('elements').is(value,'snippet')){this.content=value.data;if(this._text){this.content=require('abbreviationUtils').insertChildContent(value.data,this._text);}}}return this._data[name];},name:function(){ +var res=this.matchedResource();if(require('elements').is(res,'element')){return res.name;}return this._name;},attributeList:function(){var attrs=[];var res=this.matchedResource();if(require('elements').is(res,'element')&&_.isArray(res.attributes)){attrs=attrs.concat(res.attributes);}return optimizeAttributes(attrs.concat(this._attributes));},attribute:function(name,value){if(arguments.length==2){var ix=_.indexOf(_.pluck(this._attributes,'name'),name.toLowerCase());if(~ix){this._attributes[ix].value=value;}else{this._attributes.push({name:name,value:value});}}return(_.find(this.attributeList(),function(attr){return attr.name==name;})||{}).value;},matchedResource:function(){return this.data('resource');},index:function(){return this.parent?_.indexOf(this.parent.children,this):-1;},_setRepeat:function(count){if(count){this.repeatCount=parseInt(count,10)||1;}else{this.hasImplicitRepeat=true;}},setAbbreviation:function(abbr){abbr=abbr||'';var that=this;abbr=abbr.replace(/\*(\d+)?$/,function(str,repeatCount){ +that._setRepeat(repeatCount);return'';});this.abbreviation=abbr;var abbrText=extractText(abbr);if(abbrText){abbr=abbrText.element;this.content=this._text=abbrText.text;}var abbrAttrs=parseAttributes(abbr);if(abbrAttrs){abbr=abbrAttrs.element;this._attributes=abbrAttrs.attributes;}this._name=abbr;if(this._name&&!reValidName.test(this._name)){throw'Invalid abbreviation';}},toString:function(){var utils=require('utils');var start=this.start;var end=this.end;var content=this.content;var node=this;_.each(outputProcessors,function(fn){start=fn(start,node,'start');content=fn(content,node,'content');end=fn(end,node,'end');});var innerContent=_.map(this.children,function(child){return child.toString();}).join('');content=require('abbreviationUtils').insertChildContent(content,innerContent,{keepVariable:false});return start+utils.padString(content,this.padding)+end;},hasEmptyChildren:function(){return!!_.find(this.children,function(child){return child.isEmpty();});},hasImplicitName:function(){ +return!this._name&&!this.isTextNode();},isGroup:function(){return!this.abbreviation;},isEmpty:function(){return!this.abbreviation&&!this.children.length;},isRepeating:function(){return this.repeatCount>1||this.hasImplicitRepeat;},isTextNode:function(){return!this.name()&&!this.attributeList().length;},isElement:function(){return!this.isEmpty()&&!this.isTextNode();},deepestChild:function(){if(!this.children.length)return null;var deepestChild=this;while(deepestChild.children.length){deepestChild=_.last(deepestChild.children);}return deepestChild;}};function stripped(str){return str.substring(1,str.length-1);}function consumeQuotedValue(stream,quote){var ch;while(ch=stream.next()){if(ch===quote)return true;if(ch=='\\')continue;}return false;}function parseAbbreviation(abbr){abbr=require('utils').trim(abbr);var root=new AbbreviationNode;var context=root.addChild(),ch;var stream=require('stringStream').create(abbr);var loopProtector=1000,multiplier;while(!stream.eol()&&--loopProtector>0){ +ch=stream.peek();switch(ch){case'(':stream.start=stream.pos;if(stream.skipToPair('(',')')){var inner=parseAbbreviation(stripped(stream.current()));if(multiplier=stream.match(/^\*(\d+)?/,true)){context._setRepeat(multiplier[1]);}_.each(inner.children,function(child){context.addChild(child);});}else{throw'Invalid abbreviation: mo matching ")" found for character at '+stream.pos;}break;case'>':context=context.addChild();stream.next();break;case'+':context=context.parent.addChild();stream.next();break;case'^':var parent=context.parent||context;context=(parent.parent||parent).addChild();stream.next();break;default:stream.start=stream.pos;stream.eatWhile(function(c){if(c=='['||c=='{'){if(stream.skipToPair(c,pairs[c])){stream.backUp(1);return true;}throw'Invalid abbreviation: mo matching "'+pairs[c]+'" found for character at '+stream.pos;}if(c=='+'){stream.next();var isMarker=stream.eol()||~'+>^*'.indexOf(stream.peek());stream.backUp(1);return isMarker;}return c!='('&&isAllowedChar(c);}); +context.setAbbreviation(stream.current());stream.start=stream.pos;}}if(loopProtector<1)throw'Endless loop detected';return root;}function extractAttributes(attrSet,attrs){attrSet=require('utils').trim(attrSet);var result=[];var stream=require('stringStream').create(attrSet);stream.eatSpace();while(!stream.eol()){stream.start=stream.pos;if(stream.eatWhile(reWord)){var attrName=stream.current();var attrValue='';if(stream.peek()=='='){stream.next();stream.start=stream.pos;var quote=stream.peek();if(quote=='"'||quote=="'"){stream.next();if(consumeQuotedValue(stream,quote)){attrValue=stream.current();attrValue=attrValue.substring(1,attrValue.length-1);}else{throw'Invalid attribute value';}}else if(stream.eatWhile(/[^\s\]]/)){attrValue=stream.current();}else{throw'Invalid attribute value';}}result.push({name:attrName,value:attrValue});stream.eatSpace();}else{break;}}return result;}function parseAttributes(abbr){var result=[];var attrMap={'#':'id','.':'class'};var nameEnd=null;var stream=require('stringStream').create(abbr); +while(!stream.eol()){switch(stream.peek()){case'#':case'.':if(nameEnd===null)nameEnd=stream.pos;var attrName=attrMap[stream.peek()];stream.next();stream.start=stream.pos;stream.eatWhile(reWord);result.push({name:attrName,value:stream.current()});break;case'[':if(nameEnd===null)nameEnd=stream.pos;stream.start=stream.pos;if(!stream.skipToPair('[',']'))throw'Invalid attribute set definition';result=result.concat(extractAttributes(stripped(stream.current())));break;default:stream.next();}}if(!result.length)return null;return{element:abbr.substring(0,nameEnd),attributes:optimizeAttributes(result)};}function optimizeAttributes(attrs){attrs=_.map(attrs,function(attr){return _.clone(attr);});var lookup={};return _.filter(attrs,function(attr){if(!(attr.name in lookup)){return lookup[attr.name]=attr;}var la=lookup[attr.name];if(attr.name.toLowerCase()=='class'){la.value+=(la.value.length?' ':'')+attr.value;}else{la.value=attr.value;}return false;});}function extractText(abbr){if(!~abbr.indexOf('{')) +return null;var stream=require('stringStream').create(abbr);while(!stream.eol()){switch(stream.peek()){case'[':case'(':stream.skipToPair(stream.peek(),pairs[stream.peek()]);break;case'{':stream.start=stream.pos;stream.skipToPair('{','}');return{element:abbr.substring(0,stream.start),text:stripped(stream.current())};default:stream.next();}}}function unroll(node){for(var i=node.children.length-1,j,child,maxCount;i>=0;i--){child=node.children[i];if(child.isRepeating()){maxCount=j=child.repeatCount;child.repeatCount=1;child.updateProperty('counter',1);child.updateProperty('maxCount',maxCount);while(--j>0){child.parent.addChild(child.clone(),i+1).updateProperty('counter',j+1).updateProperty('maxCount',maxCount);}}}_.each(node.children,unroll);return node;}function squash(node){for(var i=node.children.length-1;i>=0;i--){var n=node.children[i];if(n.isGroup()){n.replace(squash(n).children);}else if(n.isEmpty()){n.remove();}}_.each(node.children,squash);return node;}function isAllowedChar(ch){ +var charCode=ch.charCodeAt(0);var specialChars='#.*:$-_!@|%';return(charCode>64&&charCode<91)||(charCode>96&&charCode<123)||(charCode>47&&charCode<58)||specialChars.indexOf(ch)!=-1;}outputProcessors.push(function(text,node){return require('utils').replaceCounter(text,node.counter,node.maxCount);});return{parse:function(abbr,options){options=options||{};var tree=parseAbbreviation(abbr);if(options.contextNode){tree._name=options.contextNode.name;var attrLookup={};_.each(tree._attributes,function(attr){attrLookup[attr.name]=attr;});_.each(options.contextNode.attributes,function(attr){if(attr.name in attrLookup){attrLookup[attr.name].value=attr.value;}else{attr=_.clone(attr);tree._attributes.push(attr);attrLookup[attr.name]=attr;}});}_.each(preprocessors,function(fn){fn(tree,options);});tree=squash(unroll(tree));_.each(postprocessors,function(fn){fn(tree,options);});return tree;},AbbreviationNode:AbbreviationNode,addPreprocessor:function(fn){if(!_.include(preprocessors,fn))preprocessors.push(fn); +},removeFilter:function(fn){preprocessor=_.without(preprocessors,fn);},addPostprocessor:function(fn){if(!_.include(postprocessors,fn))postprocessors.push(fn);},removePostprocessor:function(fn){postprocessors=_.without(postprocessors,fn);},addOutputProcessor:function(fn){if(!_.include(outputProcessors,fn))outputProcessors.push(fn);},removeOutputProcessor:function(fn){outputProcessors=_.without(outputProcessors,fn);},isAllowedChar:function(ch){ch=String(ch);return isAllowedChar(ch)||~'>+^[](){}'.indexOf(ch);}};});emmet.exec(function(require,_){function matchResources(node,syntax){var resources=require('resources');var elements=require('elements');var parser=require('abbreviationParser');_.each(_.clone(node.children),function(child){var r=resources.getMatchedResource(child,syntax);if(_.isString(r)){child.data('resource',elements.create('snippet',r));}else if(elements.is(r,'reference')){var subtree=parser.parse(r.data,{syntax:syntax});if(child.repeatCount>1){var repeatedChildren=subtree.findAll(function(node){ +return node.hasImplicitRepeat;});_.each(repeatedChildren,function(node){node.repeatCount=child.repeatCount;node.hasImplicitRepeat=false;});}var deepestChild=subtree.deepestChild();if(deepestChild){_.each(child.children,function(c){deepestChild.addChild(c);});}_.each(subtree.children,function(node){_.each(child.attributeList(),function(attr){node.attribute(attr.name,attr.value);});});child.replace(subtree.children);}else{child.data('resource',r);}matchResources(child,syntax);});}require('abbreviationParser').addPreprocessor(function(tree,options){var syntax=options.syntax||emmet.defaultSyntax();matchResources(tree,syntax);});});emmet.exec(function(require,_){var parser=require('abbreviationParser');var outputPlaceholder='$#';function locateOutputPlaceholder(text){var range=require('range');var result=[];var stream=require('stringStream').create(text);while(!stream.eol()){if(stream.peek()=='\\'){stream.next();}else{stream.start=stream.pos;if(stream.match(outputPlaceholder,true)){result.push(range.create(stream.start,outputPlaceholder)); +continue;}}stream.next();}return result;}function replaceOutputPlaceholders(source,value){var utils=require('utils');var ranges=locateOutputPlaceholder(source);ranges.reverse();_.each(ranges,function(r){source=utils.replaceSubstring(source,value,r);});return source;}function hasOutputPlaceholder(node){if(locateOutputPlaceholder(node.content).length)return true;return!!_.find(node.attributeList(),function(attr){return!!locateOutputPlaceholder(attr.value).length;});}function insertPastedContent(node,content,overwrite){var nodesWithPlaceholders=node.findAll(function(item){return hasOutputPlaceholder(item);});if(hasOutputPlaceholder(node))nodesWithPlaceholders.unshift(node);if(nodesWithPlaceholders.length){_.each(nodesWithPlaceholders,function(item){item.content=replaceOutputPlaceholders(item.content,content);_.each(item._attributes,function(attr){attr.value=replaceOutputPlaceholders(attr.value,content);});});}else{var deepest=node.deepestChild()||node;if(overwrite){deepest.content=content; +}else{deepest.content=require('abbreviationUtils').insertChildContent(deepest.content,content);}}}parser.addPreprocessor(function(tree,options){if(options.pastedContent){var utils=require('utils');var lines=_.map(utils.splitByLines(options.pastedContent,true),utils.trim);tree.findAll(function(item){if(item.hasImplicitRepeat){item.data('paste',lines);return item.repeatCount=lines.length;}});}});parser.addPostprocessor(function(tree,options){var targets=tree.findAll(function(item){var pastedContentObj=item.data('paste');var pastedContent='';if(_.isArray(pastedContentObj)){pastedContent=pastedContentObj[item.counter-1];}else if(_.isFunction(pastedContentObj)){pastedContent=pastedContentObj(item.counter-1,item.content);}else if(pastedContentObj){pastedContent=pastedContentObj;}if(pastedContent){insertPastedContent(item,pastedContent,!!item.data('pasteOverwrites'));}item.data('paste',null);return!!pastedContentObj;});if(!targets.length&&options.pastedContent){insertPastedContent(tree,options.pastedContent); +}});});emmet.exec(function(require,_){function resolveNodeNames(tree){var tagName=require('tagName');_.each(tree.children,function(node){if(node.hasImplicitName()||node.data('forceNameResolving')){node._name=tagName.resolve(node.parent.name());}resolveNodeNames(node);});return tree;}require('abbreviationParser').addPostprocessor(resolveNodeNames);});emmet.define('cssParser',function(require,_){var walker,tokens=[],isOp,isNameChar,isDigit;walker={lines:null,total_lines:0,linenum:-1,line:'',ch:'',chnum:-1,init:function(source){var me=walker;me.lines=source.replace(/\r\n/g,'\n').replace(/\r/g,'\n').split('\n');me.total_lines=me.lines.length;me.chnum=-1;me.linenum=-1;me.ch='';me.line='';me.nextLine();me.nextChar();},nextLine:function(){var me=this;me.linenum+=1;if(me.total_lines<=me.linenum){me.line=false;}else{me.line=me.lines[me.linenum];}if(me.chnum!==-1){me.chnum=0;}return me.line;},nextChar:function(){var me=this;me.chnum+=1;while(me.line.charAt(me.chnum)===''){if(this.nextLine()===false){ +me.ch=false;return false;}me.chnum=-1;me.ch='\n';return'\n';}me.ch=me.line.charAt(me.chnum);return me.ch;},peek:function(){return this.line.charAt(this.chnum+1);}};isNameChar=function(c){return(c=='&'||c==='_'||c==='-'||(c>='a'&&c<='z')||(c>='A'&&c<='Z'));};isDigit=function(ch){return(ch!==false&&ch>='0'&&ch<='9');};isOp=(function(){var opsa="{}[]()+*=.,;:>~|\\%$#@^!".split(''),opsmatcha="*^|$~".split(''),ops={},opsmatch={},i=0;for(;i"));else return null;}else if(stream.match("--"))return chain(inBlock("comment","-->"));else if(stream.match("DOCTYPE",true,true)){stream.eatWhile(/[\w\._\-]/);return chain(doctype(1));}else return null;}else if(stream.eat("?")){stream.eatWhile(/[\w\._\-]/);state.tokenize=inBlock("meta","?>");return"meta";}else{ +type=stream.eat("/")?"closeTag":"openTag";stream.eatSpace();tagName="";var c;while((c=stream.eat(/[^\s\u00a0=<>\"\'\/?]/)))tagName+=c;state.tokenize=inTag;return"tag";}}else if(ch=="&"){var ok;if(stream.eat("#")){if(stream.eat("x")){ok=stream.eatWhile(/[a-fA-F\d]/)&&stream.eat(";");}else{ok=stream.eatWhile(/[\d]/)&&stream.eat(";");}}else{ok=stream.eatWhile(/[\w\.\-:]/)&&stream.eat(";");}return ok?"atom":"error";}else{stream.eatWhile(/[^&<]/);return"text";}}function inTag(stream,state){var ch=stream.next();if(ch==">"||(ch=="/"&&stream.eat(">"))){state.tokenize=inText;type=ch==">"?"endTag":"selfcloseTag";return"tag";}else if(ch=="="){type="equals";return null;}else if(/[\'\"]/.test(ch)){state.tokenize=inAttribute(ch);return state.tokenize(stream,state);}else{stream.eatWhile(/[^\s\u00a0=<>\"\'\/?]/);return"word";}}function inAttribute(quote){return function(stream,state){while(!stream.eol()){if(stream.next()==quote){state.tokenize=inTag;break;}}return"string";};}function inBlock(style,terminator){ +return function(stream,state){while(!stream.eol()){if(stream.match(terminator)){state.tokenize=inText;break;}stream.next();}return style;};}function doctype(depth){return function(stream,state){var ch;while((ch=stream.next())!=null){if(ch=="<"){state.tokenize=doctype(depth+1);return state.tokenize(stream,state);}else if(ch==">"){if(depth==1){state.tokenize=inText;break;}else{state.tokenize=doctype(depth-1);return state.tokenize(stream,state);}}}return"meta";};}var curState=null,setStyle;function pass(){for(var i=arguments.length-1;i>=0;i--)curState.cc.push(arguments[i]);}function cont(){pass.apply(null,arguments);return true;}function pushContext(tagName,startOfLine){var noIndent=Kludges.doNotIndent.hasOwnProperty(tagName)||(curState.context&&curState.context.noIndent);curState.context={prev:curState.context,tagName:tagName,indent:curState.indented,startOfLine:startOfLine,noIndent:noIndent};}function popContext(){if(curState.context)curState.context=curState.context.prev;}function element(type){ +if(type=="openTag"){curState.tagName=tagName;return cont(attributes,endtag(curState.startOfLine));}else if(type=="closeTag"){var err=false;if(curState.context){if(curState.context.tagName!=tagName){if(Kludges.implicitlyClosed.hasOwnProperty(curState.context.tagName.toLowerCase())){popContext();}err=!curState.context||curState.context.tagName!=tagName;}}else{err=true;}if(err)setStyle="error";return cont(endclosetag(err));}return cont();}function endtag(startOfLine){return function(type){if(type=="selfcloseTag"||(type=="endTag"&&Kludges.autoSelfClosers.hasOwnProperty(curState.tagName.toLowerCase()))){maybePopContext(curState.tagName.toLowerCase());return cont();}if(type=="endTag"){maybePopContext(curState.tagName.toLowerCase());pushContext(curState.tagName,startOfLine);return cont();}return cont();};}function endclosetag(err){return function(type){if(err)setStyle="error";if(type=="endTag"){popContext();return cont();}setStyle="error";return cont(arguments.callee);};}function maybePopContext(nextTagName){ +var parentTagName;while(true){if(!curState.context){return;}parentTagName=curState.context.tagName.toLowerCase();if(!Kludges.contextGrabbers.hasOwnProperty(parentTagName)||!Kludges.contextGrabbers[parentTagName].hasOwnProperty(nextTagName)){return;}popContext();}}function attributes(type){if(type=="word"){setStyle="attribute";return cont(attribute,attributes);}if(type=="endTag"||type=="selfcloseTag")return pass();setStyle="error";return cont(attributes);}function attribute(type){if(type=="equals")return cont(attvalue,attributes);if(!Kludges.allowMissing)setStyle="error";return(type=="endTag"||type=="selfcloseTag")?pass():cont();}function attvalue(type){if(type=="string")return cont(attvaluemaybe);if(type=="word"&&Kludges.allowUnquoted){setStyle="string";return cont();}setStyle="error";return(type=="endTag"||type=="selfCloseTag")?pass():cont();}function attvaluemaybe(type){if(type=="string")return cont(attvaluemaybe);else return pass();}function startState(){return{tokenize:inText,cc:[], +indented:0,startOfLine:true,tagName:null,context:null};}function token(stream,state){if(stream.sol()){state.startOfLine=true;state.indented=0;}if(stream.eatSpace())return null;setStyle=type=tagName=null;var style=state.tokenize(stream,state);state.type=type;if((style||type)&&style!="comment"){curState=state;while(true){var comb=state.cc.pop()||element;if(comb(type||style))break;}}state.startOfLine=false;return setStyle||style;}return{parse:function(data,offset){offset=offset||0;var state=startState();var stream=require('stringStream').create(data);var tokens=[];while(!stream.eol()){tokens.push({type:token(stream,state),start:stream.start+offset,end:stream.pos+offset});stream.start=stream.pos;}return tokens;}};});emmet.define('string-score',function(require,_){return{score:function(string,abbreviation,fuzziness){if(string==abbreviation){return 1;}if(abbreviation==""){return 0;}var total_character_score=0,abbreviation_length=abbreviation.length,string_length=string.length, +start_of_string_bonus,abbreviation_score,fuzzies=1,final_score;for(var i=0,character_score,index_in_string,c,index_c_lowercase,index_c_uppercase,min_index;i-1)?min_index:Math.max(index_c_lowercase,index_c_uppercase);if(index_in_string===-1){if(fuzziness){fuzzies+=1-fuzziness;continue;}else{return 0;}}else{character_score=0.1;}if(string[index_in_string]===c){character_score+=0.1;}if(index_in_string===0){character_score+=0.6;if(i===0){start_of_string_bonus=1;}}else{if(string.charAt(index_in_string-1)===' '){character_score+=0.8;}}string=string.substring(index_in_string+1,string_length);total_character_score+=character_score;}abbreviation_score=total_character_score/abbreviation_length;final_score=((abbreviation_score*(abbreviation_length/string_length))+abbreviation_score)/2; +final_score=final_score/fuzzies;if(start_of_string_bonus&&(final_score+0.15<1)){final_score+=0.15;}return final_score;}};});emmet.define('utils',function(require,_){var caretPlaceholder='${0}';function StringBuilder(value){this._data=[];this.length=0;if(value)this.append(value);}StringBuilder.prototype={append:function(text){this._data.push(text);this.length+=text.length;},toString:function(){return this._data.join('');},valueOf:function(){return this.toString();}};return{reTag:/<\/?[\w:\-]+(?:\s+[\w\-:]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*\s*(\/?)>$/,endsWithTag:function(str){return this.reTag.test(str);},isNumeric:function(ch){if(typeof(ch)=='string')ch=ch.charCodeAt(0);return(ch&&ch>47&&ch<58);},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},getNewline:function(){var res=require('resources');if(!res){return'\n';}var nl=res.getVariable('newline');return _.isString(nl)?nl:'\n';},setNewline:function(str){var res=require('resources');res.setVariable('newline',str); +res.setVariable('nl',str);},splitByLines:function(text,removeEmpty){var nl=this.getNewline();var lines=(text||'').replace(/\r\n/g,'\n').replace(/\n\r/g,'\n').replace(/\r/g,'\n').replace(/\n/g,nl).split(nl);if(removeEmpty){lines=_.filter(lines,function(line){return line.length&&!!this.trim(line);},this);}return lines;},normalizeNewline:function(text){return this.splitByLines(text).join(this.getNewline());},repeatString:function(str,howMany){var result=[];for(var i=0;iil++)padding+='0';return padding+str;},unindentString:function(text,pad){var lines=this.splitByLines(text);for(var i=0;istr.length)return str;return str.substring(0,start)+value+str.substring(end);},narrowToNonSpace:function(text,start,end){var range=require('range').create(start,end);var reSpace=/[\s\n\r\u00a0]/;while(range.startrange.start){range.end--;if(!reSpace.test(text.charAt(range.end))){range.end++;break;}}return range;},findNewlineBounds:function(text,from){var len=text.length,start=0,end=len-1;for(var i=from-1;i>0;i--){var ch=text.charAt(i);if(ch=='\n'||ch=='\r'){start=i+1;break;}}for(var j=from;j':return a>b;case'gte':case'>=':return a>=b;}}function Range(start,len){if(_.isObject(start)&&'start'in start){this.start=Math.min(start.start,start.end);this.end=Math.max(start.start,start.end);}else if(_.isArray(start)){this.start=start[0];this.end=start[1];}else{len=_.isString(len)?len.length:+len;this.start=start;this.end=start+len;}}Range.prototype={length:function(){return Math.abs(this.end-this.start);},equal:function(range){return this.cmp(range,'eq','eq'); +},shift:function(delta){this.start+=delta;this.end+=delta;return this;},overlap:function(range){return range.start<=this.end&&range.end>=this.start;},intersection:function(range){if(this.overlap(range)){var start=Math.max(range.start,this.start);var end=Math.min(range.end,this.end);return new Range(start,end-start);}return null;},union:function(range){if(this.overlap(range)){var start=Math.min(range.start,this.start);var end=Math.max(range.end,this.end);return new Range(start,end-start);}return null;},inside:function(loc){return this.cmp(loc,'lte','gt');},contains:function(loc){return this.cmp(loc,'lt','gt');},include:function(r){return this.cmp(loc,'lte','gte');},cmp:function(loc,left,right){var a,b;if(loc instanceof Range){a=loc.start;b=loc.end;}else{a=b=loc;}return cmp(this.start,a,left||'<=')&&cmp(this.end,b,right||'>');},substring:function(str){return this.length()>0?str.substring(this.start,this.end):'';},clone:function(){return new Range(this.start,this.length());},toArray:function(){ +return[this.start,this.end];},toString:function(){return'{'+this.start+', '+this.length()+'}';}};return{create:function(start,len){if(_.isUndefined(start)||start===null)return null;if(start instanceof Range)return start;if(_.isObject(start)&&'start'in start&&'end'in start){len=start.end-start.start;start=start.start;}return new Range(start,len);},create2:function(start,end){if(_.isNumber(start)&&_.isNumber(end)){end-=start;}return this.create(start,end);}};});emmet.define('handlerList',function(require,_){function HandlerList(){this._list=[];}HandlerList.prototype={add:function(fn,options){this._list.push(_.extend({order:0},options||{},{fn:fn}));},remove:function(fn){this._list=_.without(this._list,_.find(this._list,function(item){return item.fn===fn;}));},list:function(){return _.sortBy(this._list,'order').reverse();},listFn:function(){return _.pluck(this.list(),'fn');},exec:function(skipValue,args){args=args||[];var result=null;_.find(this.list(),function(h){result=h.fn.apply(h,args); +if(result!==skipValue)return true;});return result;}};return{create:function(){return new HandlerList();}};});emmet.define('tokenIterator',function(require,_){function TokenIterator(tokens){this.tokens=tokens;this._position=0;this.reset();}TokenIterator.prototype={next:function(){if(this.hasNext()){var token=this.tokens[++this._i];this._position=token.start;return token;}return null;},current:function(){return this.tokens[this._i];},position:function(){return this._position;},hasNext:function(){return this._i=this.string.length;},sol:function(){return this.pos==0;},peek:function(){return this.string.charAt(this.pos);},next:function(){if(this.posstart;},eatSpace:function(){var start=this.pos;while(/[\s\u00a0]/.test(this.string.charAt(this.pos)))++this.pos;return this.pos>start;},skipToEnd:function(){this.pos=this.string.length;},skipTo:function(ch){var found=this.string.indexOf(ch,this.pos);if(found>-1){this.pos=found;return true;}},skipToPair:function(open,close){var braceCount=0,ch;var pos=this.pos,len=this.string.length; +while(pos/;var systemSettings={};var userSettings={};var resolvers=require('handlerList').create(); +function normalizeCaretPlaceholder(text){var utils=require('utils');return utils.replaceUnescapedSymbol(text,'|',utils.getCaretPlaceholder());}function parseItem(name,value,type){value=normalizeCaretPlaceholder(value);if(type=='snippets'){return require('elements').create('snippet',value);}if(type=='abbreviations'){return parseAbbreviation(name,value);}}function parseAbbreviation(key,value){key=require('utils').trim(key);var elements=require('elements');var m;if(m=reTag.exec(value)){return elements.create('element',m[1],m[2],m[4]=='/');}else{return elements.create('reference',value);}}function normalizeName(str){return str.replace(/:$/,'').replace(/:/g,'-');}return{setVocabulary:function(data,type){cache={};if(type==VOC_SYSTEM)systemSettings=data;else userSettings=data;},getVocabulary:function(name){return name==VOC_SYSTEM?systemSettings:userSettings;},getMatchedResource:function(node,syntax){return resolvers.exec(null,_.toArray(arguments))||this.findSnippet(syntax,node.name());}, +getVariable:function(name){return(this.getSection('variables')||{})[name];},setVariable:function(name,value){var voc=this.getVocabulary('user')||{};if(!('variables'in voc))voc.variables={};voc.variables[name]=value;this.setVocabulary(voc,'user');},hasSyntax:function(syntax){return syntax in this.getVocabulary(VOC_USER)||syntax in this.getVocabulary(VOC_SYSTEM);},addResolver:function(fn,options){resolvers.add(fn,options);},removeResolver:function(fn){resolvers.remove(fn);},getSection:function(name){if(!name)return null;if(!(name in cache)){cache[name]=require('utils').deepMerge({},systemSettings[name],userSettings[name]);}var data=cache[name],subsections=_.rest(arguments),key;while(data&&(key=subsections.shift())){if(key in data){data=data[key];}else{return null;}}return data;},findItem:function(topSection,subsection){var data=this.getSection(topSection);while(data){if(subsection in data)return data[subsection];data=this.getSection(data['extends']);}},findSnippet:function(syntax,name,memo){ +if(!syntax||!name)return null;memo=memo||[];var names=[name];if(~name.indexOf('-'))names.push(name.replace(/\-/g,':'));var data=this.getSection(syntax),matchedItem=null;_.find(['snippets','abbreviations'],function(sectionName){var data=this.getSection(syntax,sectionName);if(data){return _.find(names,function(n){if(data[n])return matchedItem=parseItem(n,data[n],sectionName);});}},this);memo.push(syntax);if(!matchedItem&&data['extends']&&!_.include(memo,data['extends'])){return this.findSnippet(data['extends'],name,memo);}return matchedItem;},fuzzyFindSnippet:function(syntax,name,minScore){minScore=minScore||0.3;var payload=this.getAllSnippets(syntax);var sc=require('string-score');name=normalizeName(name);var scores=_.map(payload,function(value,key){return{key:key,score:sc.score(value.nk,name,0.1)};});var result=_.last(_.sortBy(scores,'score'));if(result&&result.score>=minScore){var k=result.key;return payload[k].parsedValue;}},getAllSnippets:function(syntax){var cacheKey='all-'+syntax; +if(!cache[cacheKey]){var stack=[],sectionKey=syntax;var memo=[];do{var section=this.getSection(sectionKey);if(!section)break;_.each(['snippets','abbreviations'],function(sectionName){var stackItem={};_.each(section[sectionName]||null,function(v,k){stackItem[k]={nk:normalizeName(k),value:v,parsedValue:parseItem(k,v,sectionName),type:sectionName};});stack.push(stackItem);});memo.push(sectionKey);sectionKey=section['extends'];}while(sectionKey&&!_.include(memo,sectionKey));cache[cacheKey]=_.extend.apply(_,stack.reverse());}return cache[cacheKey];}};});emmet.define('actions',function(require,_,zc){var actions={};function humanizeActionName(name){return require('utils').trim(name.charAt(0).toUpperCase()+name.substring(1).replace(/_[a-z]/g,function(str){return' '+str.charAt(1).toUpperCase();}));}return{add:function(name,fn,options){name=name.toLowerCase();options=options||{};if(!options.label){options.label=humanizeActionName(name);}actions[name]={name:name,fn:fn,options:options};},get:function(name){ +return actions[name.toLowerCase()];},run:function(name,args){if(!_.isArray(args)){args=_.rest(arguments);}var action=this.get(name);if(action){return action.fn.apply(emmet,args);}else{emmet.log('Action "%s" is not defined',name);return false;}},getAll:function(){return actions;},getList:function(){return _.values(this.getAll());},getMenu:function(skipActions){var result=[];skipActions=skipActions||[];_.each(this.getList(),function(action){if(action.options.hidden||_.include(skipActions,action.name))return;var actionName=humanizeActionName(action.name);var ctx=result;if(action.options.label){var parts=action.options.label.split('/');actionName=parts.pop();var menuName,submenu;while(menuName=parts.shift()){submenu=_.find(ctx,function(item){return item.type=='submenu'&&item.name==menuName;});if(!submenu){submenu={name:menuName,type:'submenu',items:[]};ctx.push(submenu);}ctx=submenu.items;}}ctx.push({type:'action',name:action.name,label:actionName});});return result;}, +getActionNameForMenuTitle:function(title,menu){var item=null;_.find(menu||this.getMenu(),function(val){if(val.type=='action'){if(val.label==title||val.name==title){return item=val.name;}}else{return item=this.getActionNameForMenuTitle(title,val.items);}},this);return item||null;}};});emmet.define('profile',function(require,_){var profiles={};var defaultProfile={tag_case:'asis',attr_case:'asis',attr_quotes:'double',tag_nl:'decide',tag_nl_leaf:false,place_cursor:true,indent:true,inline_break:3,self_closing_tag:'xhtml',filters:'',extraFilters:''};function OutputProfile(options){_.extend(this,defaultProfile,options);}OutputProfile.prototype={tagName:function(name){return stringCase(name,this.tag_case);},attributeName:function(name){return stringCase(name,this.attr_case);},attributeQuote:function(){return this.attr_quotes=='single'?"'":'"';},selfClosing:function(param){if(this.self_closing_tag=='xhtml')return' /';if(this.self_closing_tag===true)return'/';return'';},cursor:function(){return this.place_cursor?require('utils').getCaretPlaceholder():''; +}};function stringCase(str,caseValue){switch(String(caseValue||'').toLowerCase()){case'lower':return str.toLowerCase();case'upper':return str.toUpperCase();}return str;}function createProfile(name,options){return profiles[name.toLowerCase()]=new OutputProfile(options);}function createDefaultProfiles(){createProfile('xhtml');createProfile('html',{self_closing_tag:false});createProfile('xml',{self_closing_tag:true,tag_nl:true});createProfile('plain',{tag_nl:false,indent:false,place_cursor:false});createProfile('line',{tag_nl:false,indent:false,extraFilters:'s'});}createDefaultProfiles();return{create:function(name,options){if(arguments.length==2)return createProfile(name,options);else return new OutputProfile(_.defaults(name||{},defaultProfile));},get:function(name,syntax){if(!name&&syntax){var profile=require('resources').findItem(syntax,'profile');if(profile){name=profile;}}if(!name){return profiles.plain;}if(name instanceof OutputProfile){return name;}if(_.isString(name)&&name.toLowerCase()in profiles){ +return profiles[name.toLowerCase()];}return this.create(name);},remove:function(name){name=(name||'').toLowerCase();if(name in profiles)delete profiles[name];},reset:function(){profiles={};createDefaultProfiles();},stringCase:stringCase};});emmet.define('editorUtils',function(require,_){return{isInsideTag:function(html,caretPos){var reTag=/^<\/?\w[\w\:\-]*.*?>/;var pos=caretPos;while(pos>-1){if(html.charAt(pos)=='<')break;pos--;}if(pos!=-1){var m=reTag.exec(html.substring(pos));if(m&&caretPos>pos&&caretPos'&&utils.endsWithTag(str.substring(0,curOffset+1)))){startIndex=curOffset+1;break;}}}if(startIndex!=-1&&!textCount&&!braceCount&&!groupCount)return str.substring(startIndex).replace(/^[\*\+\>\^]+/,''); +else return'';},getImageSize:function(stream){var pngMagicNum="\211PNG\r\n\032\n",jpgMagicNum="\377\330",gifMagicNum="GIF8",nextByte=function(){return stream.charCodeAt(pos++);};if(stream.substr(0,8)===pngMagicNum){var pos=stream.indexOf('IHDR')+4;return{width:(nextByte()<<24)|(nextByte()<<16)|(nextByte()<<8)|nextByte(),height:(nextByte()<<24)|(nextByte()<<16)|(nextByte()<<8)|nextByte()};}else if(stream.substr(0,4)===gifMagicNum){pos=6;return{width:nextByte()|(nextByte()<<8),height:nextByte()|(nextByte()<<8)};}else if(stream.substr(0,2)===jpgMagicNum){pos=2;var l=stream.length;while(pos=0xC0&&marker<=0xCF&&!(marker&0x4)&&!(marker&0x8)){pos+=1;return{height:(nextByte()<<8)|nextByte(),width:(nextByte()<<8)|nextByte()};}else{pos+=size-2;}}}},captureContext:function(editor){var allowedSyntaxes={'html':1,'xml':1,'xsl':1};var syntax=String(editor.getSyntax());if(syntax in allowedSyntaxes){ +var content=String(editor.getContent());var tag=require('htmlMatcher').find(content,editor.getCaretPos());if(tag&&tag.type=='tag'){var startTag=tag.open;var contextNode={name:startTag.name,attributes:[]};var tagTree=require('xmlEditTree').parse(startTag.range.substring(content));if(tagTree){contextNode.attributes=_.map(tagTree.getAll(),function(item){return{name:item.name(),value:item.value()};});}return contextNode;}}return null;},findExpressionBounds:function(editor,fn){var content=String(editor.getContent());var il=content.length;var exprStart=editor.getCaretPos()-1;var exprEnd=exprStart+1;while(exprStart>=0&&fn(content.charAt(exprStart),exprStart,content))exprStart--;while(exprEndexprStart){return require('range').create([++exprStart,exprEnd]);}},compoundUpdate:function(editor,data){if(data){var sel=editor.getSelectionRange();editor.replaceContent(data.data,data.start,data.end,true);editor.createSelection(data.caret,data.caret+sel.end-sel.start); +return true;}return false;},detectSyntax:function(editor,hint){var syntax=hint||'html';if(!require('resources').hasSyntax(syntax)){syntax='html';}if(syntax=='html'&&(this.isStyle(editor)||this.isInlineCSS(editor))){syntax='css';}return syntax;},detectProfile:function(editor){var syntax=editor.getSyntax();var profile=require('resources').findItem(syntax,'profile');if(profile){return profile;}switch(syntax){case'xml':case'xsl':return'xml';case'css':if(this.isInlineCSS(editor)){return'line';}break;case'html':var profile=require('resources').getVariable('profile');if(!profile){profile=this.isXHTML(editor)?'xhtml':'html';}return profile;}return'xhtml';},isXHTML:function(editor){return editor.getContent().search(/]+XHTML/i)!=-1;},isStyle:function(editor){var content=String(editor.getContent());var caretPos=editor.getCaretPos();var tag=require('htmlMatcher').tag(content,caretPos);return tag&&tag.open.name.toLowerCase()=='style'&&tag.innerRange.cmp(caretPos,'lte','gte');}, +isInlineCSS:function(editor){var content=String(editor.getContent());var caretPos=editor.getCaretPos();var tree=require('xmlEditTree').parseFromPosition(content,caretPos,true);if(tree){var attr=tree.itemFromPosition(caretPos,true);return attr&&attr.name().toLowerCase()=='style'&&attr.valueRange(true).cmp(caretPos,'lte','gte');}return false;}};});emmet.define('abbreviationUtils',function(require,_){return{isSnippet:function(node){return require('elements').is(node.matchedResource(),'snippet');},isUnary:function(node){if(node.children.length||node._text||this.isSnippet(node)){return false;}var r=node.matchedResource();return r&&r.is_empty;},isInline:function(node){return node.isTextNode()||!node.name()||require('tagName').isInlineLevel(node.name());},isBlock:function(node){return this.isSnippet(node)||!this.isInline(node);},isSnippet:function(node){return require('elements').is(node.matchedResource(),'snippet');},hasTagsInContent:function(node){return require('utils').matchesTag(node.content); +},hasBlockChildren:function(node){return(this.hasTagsInContent(node)&&this.isBlock(node))||_.any(node.children,function(child){return this.isBlock(child);},this);},insertChildContent:function(text,childContent,options){options=_.extend({keepVariable:true,appendIfNoChild:true},options||{});var childVariableReplaced=false;var utils=require('utils');text=utils.replaceVariables(text,function(variable,name,data){var output=variable;if(name=='child'){output=utils.padString(childContent,utils.getLinePaddingFromPosition(text,data.start));childVariableReplaced=true;if(options.keepVariable)output+=variable;}return output;});if(!childVariableReplaced&&options.appendIfNoChild){text+=childContent;}return text;}};});emmet.define('base64',function(require,_){var chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';return{encode:function(input){var output=[];var chr1,chr2,chr3,enc1,enc2,enc3,enc4,cdp1,cdp2,cdp3;var i=0,il=input.length,b64=chars;while(i>2;enc2=((chr1&3)<<4)|(chr2>>4);enc3=((chr2&15)<<2)|(chr3>>6);enc4=chr3&63;if(isNaN(cdp2)){enc3=enc4=64;}else if(isNaN(cdp3)){enc4=64;}output.push(b64.charAt(enc1)+b64.charAt(enc2)+b64.charAt(enc3)+b64.charAt(enc4));}return output.join('');},decode:function(data){var o1,o2,o3,h1,h2,h3,h4,bits,i=0,ac=0,tmpArr=[];var b64=chars,il=data.length;if(!data){return data;}data+='';do{h1=b64.indexOf(data.charAt(i++));h2=b64.indexOf(data.charAt(i++));h3=b64.indexOf(data.charAt(i++));h4=b64.indexOf(data.charAt(i++));bits=h1<<18|h2<<12|h3<<6|h4;o1=bits>>16&0xff;o2=bits>>8&0xff;o3=bits&0xff;if(h3==64){tmpArr[ac++]=String.fromCharCode(o1);}else if(h4==64){tmpArr[ac++]=String.fromCharCode(o1,o2);}else{tmpArr[ac++]=String.fromCharCode(o1,o2,o3);}}while(i\s]+))?)*)\s*(\/?)>/; +var reCloseTag=/^<\/([\w\:\-]+)[^>]*>/;function openTag(i,match){return{name:match[1],selfClose:!!match[3],range:require('range').create(i,match[0]),type:'open'};}function closeTag(i,match){return{name:match[1],range:require('range').create(i,match[0]),type:'close'};}function comment(i,match){return{range:require('range').create(i,_.isNumber(match)?match-i:match[0]),type:'comment'};}function createMatcher(text){var memo={},m;return{open:function(i){var m=this.matches(i);return m&&m.type=='open'?m:null;},close:function(i){var m=this.matches(i);return m&&m.type=='close'?m:null;},matches:function(i){var key='p'+i;if(!(key in memo)){if(text.charAt(i)=='<'){var substr=text.slice(i);if(m=substr.match(reOpenTag)){memo[key]=openTag(i,m);}else if(m=substr.match(reCloseTag)){memo[key]=closeTag(i,m);}else{memo[key]=false;}}}return memo[key];},text:function(){return text;}};}function matches(text,pos,pattern){return text.substring(pos,pos+pattern.length)==pattern;}function findClosingPair(open,matcher){ +var stack=[],tag=null;var text=matcher.text();for(var pos=open.range.end,len=text.length;pos')){pos=j+3;break;}}}if(tag=matcher.matches(pos)){if(tag.type=='open'&&!tag.selfClose){stack.push(tag.name);}else if(tag.type=='close'){if(!stack.length){return tag.name==open.name?tag:null;}if(_.last(stack)==tag.name){stack.pop();}else{var found=false;while(stack.length&&!found){var last=stack.pop();if(last==tag.name){found=true;}}if(!stack.length&&!found){return tag.name==open.name?tag:null;}}}}}}return{find:function(text,pos){var range=require('range');var matcher=createMatcher(text);var open=null,close=null;for(var i=pos;i>=0;i--){if(open=matcher.open(i)){if(open.selfClose){if(open.range.cmp(pos,'lt','gt')){break;}continue;}close=findClosingPair(open,matcher);if(close){var r=range.create2(open.range.start,close.range.end);if(r.contains(pos)){break;}}else if(open.range.contains(pos)){break;}open=null;}else if(matches(text,i,'-->')){ +for(var j=i-1;j>=0;j--){if(matches(text,j,'-->')){break;}else if(matches(text,j,'')){j+=3;break;}}open=comment(i,j);break;}}if(open){var outerRange=null;var innerRange=null;if(close){outerRange=range.create2(open.range.start,close.range.end);innerRange=range.create2(open.range.end,close.range.start);}else{outerRange=innerRange=range.create2(open.range.start,open.range.end);}if(open.type=='comment'){var _c=outerRange.substring(text);innerRange.start+=_c.length-_c.replace(/^<\!--\s*/,'').length;innerRange.end-=_c.length-_c.replace(/\s*-->$/,'').length;}return{open:open,close:close,type:open.type=='comment'?'comment':'tag',innerRange:innerRange,innerContent:function(){return this.innerRange.substring(text);},outerRange:outerRange,outerContent:function(){return this.outerRange.substring(text);},range:!innerRange.length()||!innerRange.cmp(pos,'lte','gte')?outerRange:innerRange, +content:function(){return this.range.substring(text);},source:text};}},tag:function(text,pos){var result=this.find(text,pos);if(result&&result.type=='tag'){return result;}}};});emmet.define('tabStops',function(require,_){var startPlaceholderNum=100;var tabstopIndex=0;var defaultOptions={replaceCarets:false,escape:function(ch){return'\\'+ch;},tabstop:function(data){return data.token;},variable:function(data){return data.token;}};require('abbreviationParser').addOutputProcessor(function(text,node,type){var maxNum=0;var tabstops=require('tabStops');var utils=require('utils');var tsOptions={tabstop:function(data){var group=parseInt(data.group);if(group==0)return'${0}';if(group>maxNum)maxNum=group;if(data.placeholder){var ix=group+tabstopIndex;var placeholder=tabstops.processText(data.placeholder,tsOptions);return'${'+ix+':'+placeholder+'}';}else{return'${'+(group+tabstopIndex)+'}';}}};text=tabstops.processText(text,tsOptions);text=utils.replaceVariables(text,tabstops.variablesResolver(node)); +tabstopIndex+=maxNum+1;return text;});return{extract:function(text,options){var utils=require('utils');var placeholders={carets:''};var marks=[];options=_.extend({},defaultOptions,options,{tabstop:function(data){var token=data.token;var ret='';if(data.placeholder=='cursor'){marks.push({start:data.start,end:data.start+token.length,group:'carets',value:''});}else{if('placeholder'in data)placeholders[data.group]=data.placeholder;if(data.group in placeholders)ret=placeholders[data.group];marks.push({start:data.start,end:data.start+token.length,group:data.group,value:ret});}return token;}});if(options.replaceCarets){text=text.replace(new RegExp(utils.escapeForRegexp(utils.getCaretPlaceholder()),'g'),'${0:cursor}');}text=this.processText(text,options);var buf=utils.stringBuilder(),lastIx=0;var tabStops=_.map(marks,function(mark){buf.append(text.substring(lastIx,mark.start));var pos=buf.length;var ph=placeholders[mark.group]||'';buf.append(ph);lastIx=mark.end;return{group:mark.group,start:pos, +end:pos+ph.length};});buf.append(text.substring(lastIx));return{text:buf.toString(),tabstops:_.sortBy(tabStops,'start')};},processText:function(text,options){options=_.extend({},defaultOptions,options);var buf=require('utils').stringBuilder();var stream=require('stringStream').create(text);var ch,m,a;while(ch=stream.next()){if(ch=='\\'&&!stream.eol()){buf.append(options.escape(stream.next()));continue;}a=ch;if(ch=='$'){stream.start=stream.pos-1;if(m=stream.match(/^[0-9]+/)){a=options.tabstop({start:buf.length,group:stream.current().substr(1),token:stream.current()});}else if(m=stream.match(/^\{([a-z_\-][\w\-]*)\}/)){a=options.variable({start:buf.length,name:m[1],token:stream.current()});}else if(m=stream.match(/^\{([0-9]+)(:.+?)?\}/,false)){stream.skipToPair('{','}');var obj={start:buf.length,group:m[1],token:stream.current()};var placeholder=obj.token.substring(obj.group.length+2,obj.token.length-1);if(placeholder){obj.placeholder=placeholder.substr(1);}a=options.tabstop(obj);}}buf.append(a); +}return buf.toString();},upgrade:function(node,offset){var maxNum=0;var options={tabstop:function(data){var group=parseInt(data.group);if(group>maxNum)maxNum=group;if(data.placeholder)return'${'+(group+offset)+':'+data.placeholder+'}';else return'${'+(group+offset)+'}';}};_.each(['start','end','content'],function(p){node[p]=this.processText(node[p],options);},this);return maxNum;},variablesResolver:function(node){var placeholderMemo={};var res=require('resources');return function(str,varName){if(varName=='child')return str;if(varName=='cursor')return require('utils').getCaretPlaceholder();var attr=node.attribute(varName);if(!_.isUndefined(attr)&&attr!==str){return attr;}var varValue=res.getVariable(varName);if(varValue)return varValue;if(!placeholderMemo[varName])placeholderMemo[varName]=startPlaceholderNum++;return'${'+placeholderMemo[varName]+':'+varName+'}';};},resetTabstopIndex:function(){tabstopIndex=0;startPlaceholderNum=100;}};});emmet.define('preferences',function(require,_){ +var preferences={};var defaults={};var _dbgDefaults=null;var _dbgPreferences=null;function toBoolean(val){if(_.isString(val)){val=val.toLowerCase();return val=='yes'||val=='true'||val=='1';}return!!val;}function isValueObj(obj){return _.isObject(obj)&&'value'in obj&&_.keys(obj).length<3;}return{define:function(name,value,description){var prefs=name;if(_.isString(name)){prefs={};prefs[name]={value:value,description:description};}_.each(prefs,function(v,k){defaults[k]=isValueObj(v)?v:{value:v};});},set:function(name,value){var prefs=name;if(_.isString(name)){prefs={};prefs[name]=value;}_.each(prefs,function(v,k){if(!(k in defaults)){throw'Property "'+k+'" is not defined. You should define it first with `define` method of current module';}if(v!==defaults[k].value){switch(typeof defaults[k].value){case'boolean':v=toBoolean(v);break;case'number':v=parseInt(v+'',10)||0;break;default:if(v!==null){v+='';}}preferences[k]=v;}else if(k in preferences){delete preferences[k];}});},get:function(name){ +if(name in preferences)return preferences[name];if(name in defaults)return defaults[name].value;return void 0;},getArray:function(name){var val=this.get(name);if(_.isUndefined(val)||val===null||val===''){return null;}val=_.map(val.split(','),require('utils').trim);if(!val.length){return null;}return val;},getDict:function(name){var result={};_.each(this.getArray(name),function(val){var parts=val.split(':');result[parts[0]]=parts[1];});return result;},description:function(name){return name in defaults?defaults[name].description:void 0;},remove:function(name){if(!_.isArray(name))name=[name];_.each(name,function(key){if(key in preferences)delete preferences[key];if(key in defaults)delete defaults[key];});},list:function(){return _.map(_.keys(defaults).sort(),function(key){return{name:key,value:this.get(key),type:typeof defaults[key].value,description:defaults[key].description};},this);},load:function(json){_.each(json,function(value,key){this.set(key,value);},this);},exportModified:function(){ +return _.clone(preferences);},reset:function(){preferences={};},_startTest:function(){_dbgDefaults=defaults;_dbgPreferences=preferences;defaults={};preferences={};},_stopTest:function(){defaults=_dbgDefaults;preferences=_dbgPreferences;}};});emmet.define('filters',function(require,_){var registeredFilters={};var basicFilters='html';function list(filters){if(!filters)return[];if(_.isString(filters))return filters.split(/[\|,]/g);return filters;}return{add:function(name,fn){registeredFilters[name]=fn;},apply:function(tree,filters,profile){var utils=require('utils');profile=require('profile').get(profile);_.each(list(filters),function(filter){var name=utils.trim(filter.toLowerCase());if(name&&name in registeredFilters){tree=registeredFilters[name](tree,profile);}});return tree;},composeList:function(syntax,profile,additionalFilters){profile=require('profile').get(profile);var filters=list(profile.filters||require('resources').findItem(syntax,'filters')||basicFilters);if(profile.extraFilters){ +filters=filters.concat(list(profile.extraFilters));}if(additionalFilters){filters=filters.concat(list(additionalFilters));}if(!filters||!filters.length){filters=list(basicFilters);}return filters;},extractFromAbbreviation:function(abbr){var filters='';abbr=abbr.replace(/\|([\w\|\-]+)$/,function(str,p1){filters=p1;return'';});return[abbr,list(filters)];}};});emmet.define('elements',function(require,_){var factories={};var reAttrs=/([\w\-:]+)\s*=\s*(['"])(.*?)\2/g;var result={add:function(name,factory){var that=this;factories[name]=function(){var elem=factory.apply(that,arguments);if(elem)elem.type=name;return elem;};},get:function(name){return factories[name];},create:function(name){var args=[].slice.call(arguments,1);var factory=this.get(name);return factory?factory.apply(this,args):null;},is:function(elem,type){return elem&&elem.type===type;}};function commonFactory(value){return{data:value};}result.add('element',function(elementName,attrs,isEmpty){var ret={name:elementName,is_empty:!!isEmpty +};if(attrs){ret.attributes=[];if(_.isArray(attrs)){ret.attributes=attrs;}else if(_.isString(attrs)){var m;while(m=reAttrs.exec(attrs)){ret.attributes.push({name:m[1],value:m[3]});}}else{_.each(attrs,function(value,name){ret.attributes.push({name:name,value:value});});}}return ret;});result.add('snippet',commonFactory);result.add('reference',commonFactory);result.add('empty',function(){return{};});return result;});emmet.define('editTree',function(require,_,core){var range=require('range').create;function EditContainer(source,options){this.options=_.extend({offset:0},options);this.source=source;this._children=[];this._positions={name:0};this.initialize.apply(this,arguments);}EditContainer.extend=core.extend;EditContainer.prototype={initialize:function(){},_updateSource:function(value,start,end){var r=range(start,_.isUndefined(end)?0:end-start);var delta=value.length-r.length();var update=function(obj){_.each(obj,function(v,k){if(v>=r.end)obj[k]+=delta;});};update(this._positions);_.each(this.list(),function(item){ +update(item._positions);});this.source=require('utils').replaceSubstring(this.source,value,r);},add:function(name,value,pos){var item=new EditElement(name,value);this._children.push(item);return item;},get:function(name){if(_.isNumber(name))return this.list()[name];if(_.isString(name))return _.find(this.list(),function(prop){return prop.name()===name;});return name;},getAll:function(name){if(!_.isArray(name))name=[name];var names=[],indexes=[];_.each(name,function(item){if(_.isString(item))names.push(item);else if(_.isNumber(item))indexes.push(item);});return _.filter(this.list(),function(attribute,i){return _.include(indexes,i)||_.include(names,attribute.name());});},value:function(name,value,pos){var element=this.get(name);if(element)return element.value(value);if(!_.isUndefined(value)){return this.add(name,value,pos);}},values:function(name){return _.map(this.getAll(name),function(element){return element.value();});},remove:function(name){var element=this.get(name);if(element){this._updateSource('',element.fullRange()); +this._children=_.without(this._children,element);}},list:function(){return this._children;},indexOf:function(item){return _.indexOf(this.list(),this.get(item));},name:function(val){if(!_.isUndefined(val)&&this._name!==(val=String(val))){this._updateSource(val,this._positions.name,this._positions.name+this._name.length);this._name=val;}return this._name;},nameRange:function(isAbsolute){return range(this._positions.name+(isAbsolute?this.options.offset:0),this.name());},range:function(isAbsolute){return range(isAbsolute?this.options.offset:0,this.toString());},itemFromPosition:function(pos,isAbsolute){return _.find(this.list(),function(elem){return elem.range(isAbsolute).inside(pos);});},toString:function(){return this.source;}};function EditElement(parent,nameToken,valueToken){this.parent=parent;this._name=nameToken.value;this._value=valueToken?valueToken.value:'';this._positions={name:nameToken.start,value:valueToken?valueToken.start:-1};this.initialize.apply(this,arguments);} +EditElement.extend=core.extend;EditElement.prototype={initialize:function(){},_pos:function(num,isAbsolute){return num+(isAbsolute?this.parent.options.offset:0);},value:function(val){if(!_.isUndefined(val)&&this._value!==(val=String(val))){this.parent._updateSource(val,this.valueRange());this._value=val;}return this._value;},name:function(val){if(!_.isUndefined(val)&&this._name!==(val=String(val))){this.parent._updateSource(val,this.nameRange());this._name=val;}return this._name;},namePosition:function(isAbsolute){return this._pos(this._positions.name,isAbsolute);},valuePosition:function(isAbsolute){return this._pos(this._positions.value,isAbsolute);},range:function(isAbsolute){return range(this.namePosition(isAbsolute),this.toString());},fullRange:function(isAbsolute){return this.range(isAbsolute);},nameRange:function(isAbsolute){return range(this.namePosition(isAbsolute),this.name());},valueRange:function(isAbsolute){return range(this.valuePosition(isAbsolute),this.value());}, +toString:function(){return this.name()+this.value();},valueOf:function(){return this.toString();}};return{EditContainer:EditContainer,EditElement:EditElement,createToken:function(start,value,type){var obj={start:start||0,value:value||'',type:type};obj.end=obj.start+obj.value.length;return obj;}};});emmet.define('cssEditTree',function(require,_){var defaultOptions={styleBefore:'\n\t',styleSeparator:': ',offset:0};var WHITESPACE_REMOVE_FROM_START=1;var WHITESPACE_REMOVE_FROM_END=2;function range(start,len){return require('range').create(start,len);}function trimWhitespaceTokens(tokens,mask){mask=mask||(WHITESPACE_REMOVE_FROM_START|WHITESPACE_REMOVE_FROM_END);var whitespace=['white','line'];if((mask&WHITESPACE_REMOVE_FROM_END)==WHITESPACE_REMOVE_FROM_END)while(tokens.length&&_.include(whitespace,_.last(tokens).type)){tokens.pop();}if((mask&WHITESPACE_REMOVE_FROM_START)==WHITESPACE_REMOVE_FROM_START)while(tokens.length&&_.include(whitespace,tokens[0].type)){tokens.shift();}return tokens;} +function findSelectorRange(it){var tokens=[],token;var start=it.position(),end;while(token=it.next()){if(token.type=='{')break;tokens.push(token);}trimWhitespaceTokens(tokens);if(tokens.length){start=tokens[0].start;end=_.last(tokens).end;}else{end=start;}return range(start,end-start);}function findValueRange(it){var skipTokens=['white','line',':'];var tokens=[],token,start,end;it.nextUntil(function(tok){return!_.include(skipTokens,this.itemNext().type);});start=it.current().end;while(token=it.next()){if(token.type=='}'||token.type==';'){trimWhitespaceTokens(tokens,WHITESPACE_REMOVE_FROM_START|(token.type=='}'?WHITESPACE_REMOVE_FROM_END:0));if(tokens.length){start=tokens[0].start;end=_.last(tokens).end;}else{end=start;}return range(start,end-start);}tokens.push(token);}if(tokens.length){return range(tokens[0].start,_.last(tokens).end-tokens[0].start);}}function findParts(str){var stream=require('stringStream').create(str);var ch;var result=[];var sep=/[\s\u00a0,]/;var add=function(){ +stream.next();result.push(range(stream.start,stream.current()));stream.start=stream.pos;};stream.eatSpace();stream.start=stream.pos;while(ch=stream.next()){if(ch=='"'||ch=="'"){stream.next();if(!stream.skipTo(ch))break;add();}else if(ch=='('){stream.backUp(1);if(!stream.skipToPair('(',')'))break;stream.backUp(1);add();}else{if(sep.test(ch)){result.push(range(stream.start,stream.current().length-1));stream.eatWhile(sep);stream.start=stream.pos;}}}add();return _.chain(result).filter(function(item){return!!item.length();}).uniq(false,function(item){return item.toString();}).value();}function isValidIdentifier(it){var tokens=it.tokens;for(var i=it._i+1,il=tokens.length;i1){p.styleBefore='\n'+_.last(lines);}p.styleSeparator=source.substring(p.nameRange().end,p.valuePosition());p.styleBefore=_.last(p.styleBefore.split('*/'));p.styleSeparator=p.styleSeparator.replace(/\/\*.*?\*\//g,'');start=p.range().end;});},add:function(name,value,pos){var list=this.list();var start=this._positions.contentStart;var styles=_.pick(this.options,'styleBefore','styleSeparator');var editTree=require('editTree');if(_.isUndefined(pos))pos=list.length;var donor=list[pos];if(donor){start=donor.fullRange().start;}else if(donor=list[pos-1]){donor.end(';');start=donor.range().end;}if(donor){styles=_.pick(donor,'styleBefore','styleSeparator');}var nameToken=editTree.createToken(start+styles.styleBefore.length,name);var valueToken=editTree.createToken(nameToken.end+styles.styleSeparator.length,value);var property=new CSSEditElement(this,nameToken,valueToken,editTree.createToken(valueToken.end,';'));_.extend(property,styles);this._updateSource(property.styleBefore+property.toString(),start); +this._children.splice(pos,0,property);return property;}});var CSSEditElement=require('editTree').EditElement.extend({initialize:function(rule,name,value,end){this.styleBefore=rule.options.styleBefore;this.styleSeparator=rule.options.styleSeparator;this._end=end.value;this._positions.end=end.start;},valueParts:function(isAbsolute){var parts=findParts(this.value());if(isAbsolute){var offset=this.valuePosition(true);_.each(parts,function(p){p.shift(offset);});}return parts;},end:function(val){if(!_.isUndefined(val)&&this._end!==val){this.parent._updateSource(val,this._positions.end,this._positions.end+this._end.length);this._end=val;}return this._end;},fullRange:function(isAbsolute){var r=this.range(isAbsolute);r.start-=this.styleBefore.length;return r;},toString:function(){return this.name()+this.styleSeparator+this.value()+this.end();}});return{parse:function(source,options){return new CSSEditContainer(source,options);},parseFromPosition:function(content,pos,isBackward){var bounds=this.extractRule(content,pos,isBackward); +if(!bounds||!bounds.inside(pos))return null;return this.parse(bounds.substring(content),{offset:bounds.start});},extractRule:function(content,pos,isBackward){var result='';var len=content.length;var offset=pos;var stopChars='{}/\\<>\n\r';var bracePos=-1,ch;while(offset>=0){ch=content.charAt(offset);if(ch=='{'){bracePos=offset;break;}else if(ch=='}'&&!isBackward){offset++;break;}offset--;}while(offset=0){ch=content.charAt(offset);if(stopChars.indexOf(ch)!=-1)break;offset--;}selector=content.substring(offset+1,bracePos).replace(/^[\s\n\r]+/m,'');return require('range').create(bracePos-selector.length,result.length+selector.length);}return null;},baseName:function(name){return name.replace(/^\s*\-\w+\-/,'');},findParts:findParts};});emmet.define('xmlEditTree',function(require,_){ +var defaultOptions={styleBefore:' ',styleSeparator:'=',styleQuote:'"',offset:0};var startTag=/^<([\w\:\-]+)((?:\s+[\w\-:]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/m;var XMLEditContainer=require('editTree').EditContainer.extend({initialize:function(source,options){_.defaults(this.options,defaultOptions);this._positions.name=1;var attrToken=null;var tokens=require('xmlParser').parse(source);var range=require('range');_.each(tokens,function(token){token.value=range.create(token).substring(source);switch(token.type){case'tag':if(/^<[^\/]+/.test(token.value)){this._name=token.value.substring(1);}break;case'attribute':if(attrToken){this._children.push(new XMLEditElement(this,attrToken));}attrToken=token;break;case'string':this._children.push(new XMLEditElement(this,attrToken,token));attrToken=null;break;}},this);if(attrToken){this._children.push(new XMLEditElement(this,attrToken));}this._saveStyle();},_saveStyle:function(){var start=this.nameRange().end;var source=this.source; +_.each(this.list(),function(p){p.styleBefore=source.substring(start,p.namePosition());if(p.valuePosition()!==-1){p.styleSeparator=source.substring(p.namePosition()+p.name().length,p.valuePosition()-p.styleQuote.length);}start=p.range().end;});},add:function(name,value,pos){var list=this.list();var start=this.nameRange().end;var editTree=require('editTree');var styles=_.pick(this.options,'styleBefore','styleSeparator','styleQuote');if(_.isUndefined(pos))pos=list.length;var donor=list[pos];if(donor){start=donor.fullRange().start;}else if(donor=list[pos-1]){start=donor.range().end;}if(donor){styles=_.pick(donor,'styleBefore','styleSeparator','styleQuote');}value=styles.styleQuote+value+styles.styleQuote;var attribute=new XMLEditElement(this,editTree.createToken(start+styles.styleBefore.length,name),editTree.createToken(start+styles.styleBefore.length+name.length+styles.styleSeparator.length,value));_.extend(attribute,styles);this._updateSource(attribute.styleBefore+attribute.toString(),start); +this._children.splice(pos,0,attribute);return attribute;}});var XMLEditElement=require('editTree').EditElement.extend({initialize:function(parent,nameToken,valueToken){this.styleBefore=parent.options.styleBefore;this.styleSeparator=parent.options.styleSeparator;var value='',quote=parent.options.styleQuote;if(valueToken){value=valueToken.value;quote=value.charAt(0);if(quote=='"'||quote=="'"){value=value.substring(1);}else{quote='';}if(quote&&value.charAt(value.length-1)==quote){value=value.substring(0,value.length-1);}}this.styleQuote=quote;this._value=value;this._positions.value=valueToken?valueToken.start+quote.length:-1;},fullRange:function(isAbsolute){var r=this.range(isAbsolute);r.start-=this.styleBefore.length;return r;},toString:function(){return this.name()+this.styleSeparator+this.styleQuote+this.value()+this.styleQuote;}});return{parse:function(source,options){return new XMLEditContainer(source,options);},parseFromPosition:function(content,pos,isBackward){var bounds=this.extractTag(content,pos,isBackward); +if(!bounds||!bounds.inside(pos))return null;return this.parse(bounds.substring(content),{offset:bounds.start});},extractTag:function(content,pos,isBackward){var len=content.length,i;var range=require('range');var maxLen=Math.min(2000,len);var r=null;var match=function(pos){var m;if(content.charAt(pos)=='<'&&(m=content.substr(pos,maxLen).match(startTag)))return range.create(pos,m[0]);};for(i=pos;i>=0;i--){if(r=match(i))break;}if(r&&(r.inside(pos)||isBackward))return r;if(!r&&isBackward)return null;for(i=pos;i',range);}function toggleCSSComment(editor){var range=require('range').create(editor.getSelectionRange());var info=require('editorUtils').outputInfo(editor);if(!range.length()){var rule=require('cssEditTree').parseFromPosition(info.content,editor.getCaretPos());if(rule){var property=cssItemFromPosition(rule,editor.getCaretPos());range=property?property.range(true):require('range').create(rule.nameRange(true).start,rule.source);}}if(!range.length()){range=require('range').create(editor.getCurrentLineRange());require('utils').narrowToNonSpace(info.content,range);}return genericCommentToggle(editor,'/*','*/',range);}function cssItemFromPosition(rule,absPos){var relPos=absPos-(rule.options.offset||0); +var reSafeChar=/^[\s\n\r]/;return _.find(rule.list(),function(item){if(item.range().end===relPos){return reSafeChar.test(rule.source.charAt(relPos));}return item.range().inside(relPos);});}function searchComment(text,from,startToken,endToken){var commentStart=-1;var commentEnd=-1;var hasMatch=function(str,start){return text.substr(start,str.length)==str;};while(from--){if(hasMatch(startToken,from)){commentStart=from;break;}}if(commentStart!=-1){from=commentStart;var contentLen=text.length;while(contentLen>=from++){if(hasMatch(endToken,from)){commentEnd=from+endToken.length;break;}}}return(commentStart!=-1&&commentEnd!=-1)?require('range').create(commentStart,commentEnd-commentStart):null;}function genericCommentToggle(editor,commentStart,commentEnd,range){var editorUtils=require('editorUtils');var content=editorUtils.outputInfo(editor).content;var caretPos=editor.getCaretPos();var newContent=null;var utils=require('utils');function removeComment(str){return str.replace(new RegExp('^'+utils.escapeForRegexp(commentStart)+'\\s*'),function(str){ +caretPos-=str.length;return'';}).replace(new RegExp('\\s*'+utils.escapeForRegexp(commentEnd)+'$'),'');}var commentRange=searchComment(content,caretPos,commentStart,commentEnd);if(commentRange&&commentRange.overlap(range)){range=commentRange;newContent=removeComment(range.substring(content));}else{newContent=commentStart+' '+range.substring(content).replace(new RegExp(utils.escapeForRegexp(commentStart)+'\\s*|\\s*'+utils.escapeForRegexp(commentEnd),'g'),'')+' '+commentEnd;caretPos+=commentStart.length+1;}if(newContent!==null){newContent=utils.escapeText(newContent);editor.setCaretPos(range.start);editor.replaceContent(editorUtils.unindent(editor,newContent),range.start,range.end);editor.setCaretPos(caretPos);return true;}return false;}require('actions').add('toggle_comment',function(editor){var info=require('editorUtils').outputInfo(editor);if(info.syntax=='css'){var caretPos=editor.getCaretPos();var tag=require('htmlMatcher').tag(info.content,caretPos);if(tag&&tag.open.range.inside(caretPos)){ +info.syntax='html';}}if(info.syntax=='css')return toggleCSSComment(editor);return toggleHTMLComment(editor);});});emmet.exec(function(require,_){function findNewEditPoint(editor,inc,offset){inc=inc||1;offset=offset||0;var curPoint=editor.getCaretPos()+offset;var content=String(editor.getContent());var maxLen=content.length;var nextPoint=-1;var reEmptyLine=/^\s+$/;function getLine(ix){var start=ix;while(start>=0){var c=content.charAt(start);if(c=='\n'||c=='\r')break;start--;}return content.substring(start,ix);}while(curPoint<=maxLen&&curPoint>=0){curPoint+=inc;var curChar=content.charAt(curPoint);var nextChar=content.charAt(curPoint+1);var prevChar=content.charAt(curPoint-1);switch(curChar){case'"':case'\'':if(nextChar==curChar&&prevChar=='='){nextPoint=curPoint+1;}break;case'>':if(nextChar=='<'){nextPoint=curPoint+1;}break;case'\n':case'\r':if(reEmptyLine.test(getLine(curPoint-1))){nextPoint=curPoint;}break;}if(nextPoint!=-1)break;}return nextPoint;}var actions=require('actions'); +actions.add('prev_edit_point',function(editor){var curPos=editor.getCaretPos();var newPoint=findNewEditPoint(editor,-1);if(newPoint==curPos)newPoint=findNewEditPoint(editor,-1,-2);if(newPoint!=-1){editor.setCaretPos(newPoint);return true;}return false;},{label:'Previous Edit Point'});actions.add('next_edit_point',function(editor){var newPoint=findNewEditPoint(editor,1);if(newPoint!=-1){editor.setCaretPos(newPoint);return true;}return false;});});emmet.exec(function(require,_){var startTag=/^<([\w\:\-]+)((?:\s+[\w\-:]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;function findItem(editor,isBackward,extractFn,rangeFn){var range=require('range');var content=require('editorUtils').outputInfo(editor).content;var contentLength=content.length;var itemRange,rng;var prevRange=range.create(-1,0);var sel=range.create(editor.getSelectionRange());var searchPos=sel.start,loop=100000;while(searchPos>=0&&searchPos0){if((itemRange=extractFn(content,searchPos,isBackward))){ +if(prevRange.equal(itemRange)){break;}prevRange=itemRange.clone();rng=rangeFn(itemRange.substring(content),itemRange.start,sel.clone());if(rng){editor.createSelection(rng.start,rng.end);return true;}else{searchPos=isBackward?itemRange.start:itemRange.end-1;}}searchPos+=isBackward?-1:1;}return false;}function findNextHTMLItem(editor){var isFirst=true;return findItem(editor,false,function(content,searchPos){if(isFirst){isFirst=false;return findOpeningTagFromPosition(content,searchPos);}else{return getOpeningTagFromPosition(content,searchPos);}},function(tag,offset,selRange){return getRangeForHTMLItem(tag,offset,selRange,false);});}function findPrevHTMLItem(editor){return findItem(editor,true,getOpeningTagFromPosition,function(tag,offset,selRange){return getRangeForHTMLItem(tag,offset,selRange,true);});}function makePossibleRangesHTML(source,tokens,offset){offset=offset||0;var range=require('range');var result=[];var attrStart=-1,attrName='',attrValue='',attrValueRange,tagName;_.each(tokens,function(tok){ +switch(tok.type){case'tag':tagName=source.substring(tok.start,tok.end);if(/^<[\w\:\-]/.test(tagName)){result.push(range.create({start:tok.start+1,end:tok.end}));}break;case'attribute':attrStart=tok.start;attrName=source.substring(tok.start,tok.end);break;case'string':result.push(range.create(attrStart,tok.end-attrStart));attrValueRange=range.create(tok);attrValue=attrValueRange.substring(source);if(isQuote(attrValue.charAt(0)))attrValueRange.start++;if(isQuote(attrValue.charAt(attrValue.length-1)))attrValueRange.end--;result.push(attrValueRange);if(attrName=='class'){result=result.concat(classNameRanges(attrValueRange.substring(source),attrValueRange.start));}break;}});_.each(result,function(r){r.shift(offset);});return _.chain(result).filter(function(item){return!!item.length();}).uniq(false,function(item){return item.toString();}).value();}function classNameRanges(className,offset){offset=offset||0;var result=[];var stream=require('stringStream').create(className);var range=require('range'); +stream.eatSpace();stream.start=stream.pos;var ch;while(ch=stream.next()){if(/[\s\u00a0]/.test(ch)){result.push(range.create(stream.start+offset,stream.pos-stream.start-1));stream.eatSpace();stream.start=stream.pos;}}result.push(range.create(stream.start+offset,stream.pos-stream.start));return result;}function getRangeForHTMLItem(tag,offset,selRange,isBackward){var ranges=makePossibleRangesHTML(tag,require('xmlParser').parse(tag),offset);if(isBackward)ranges.reverse();var curRange=_.find(ranges,function(r){return r.equal(selRange);});if(curRange){var ix=_.indexOf(ranges,curRange);if(ix1)return matchedRanges[1];}return _.find(ranges,function(r){return r.end>selRange.end;});}function findOpeningTagFromPosition(html,pos){var tag;while(pos>=0){if(tag=getOpeningTagFromPosition(html,pos)) +return tag;pos--;}return null;}function getOpeningTagFromPosition(html,pos){var m;if(html.charAt(pos)=='<'&&(m=html.substring(pos,html.length).match(startTag))){return require('range').create(pos,m[0]);}}function isQuote(ch){return ch=='"'||ch=="'";}function makePossibleRangesCSS(property){var valueRange=property.valueRange(true);var result=[property.range(true),valueRange];var stringStream=require('stringStream');var cssEditTree=require('cssEditTree');var range=require('range');var value=property.value();_.each(property.valueParts(),function(r){var clone=r.clone();result.push(clone.shift(valueRange.start));var stream=stringStream.create(r.substring(value));if(stream.match(/^[\w\-]+\(/,true)){stream.start=stream.pos;stream.skipToPair('(',')');var fnBody=stream.current();result.push(range.create(clone.start+stream.start,fnBody));_.each(cssEditTree.findParts(fnBody),function(part){result.push(range.create(clone.start+stream.start+part.start,part.substring(fnBody)));});}});return _.chain(result) +.filter(function(item){return!!item.length();}).uniq(false,function(item){return item.toString();}).value();}function matchedRangeForCSSProperty(rule,selRange,isBackward){var property=null;var possibleRanges,curRange=null,ix;var list=rule.list();var searchFn,nearestItemFn;if(isBackward){list.reverse();searchFn=function(p){return p.range(true).start<=selRange.start;};nearestItemFn=function(r){return r.start=selRange.end;};nearestItemFn=function(r){return r.end>selRange.start;};}while(property=_.find(list,searchFn)){possibleRanges=makePossibleRangesCSS(property);if(isBackward)possibleRanges.reverse();curRange=_.find(possibleRanges,function(r){return r.equal(selRange);});if(!curRange){var matchedRanges=_.filter(possibleRanges,function(r){return r.inside(selRange.end);});if(matchedRanges.length>1){curRange=matchedRanges[1];break;}if(curRange=_.find(possibleRanges,nearestItemFn))break;}else{ix=_.indexOf(possibleRanges,curRange); +if(ix!=possibleRanges.length-1){curRange=possibleRanges[ix+1];break;}}curRange=null;selRange.start=selRange.end=isBackward?property.range(true).start-1:property.range(true).end+1;}return curRange;}function findNextCSSItem(editor){return findItem(editor,false,require('cssEditTree').extractRule,getRangeForNextItemInCSS);}function findPrevCSSItem(editor){return findItem(editor,true,require('cssEditTree').extractRule,getRangeForPrevItemInCSS);}function getRangeForNextItemInCSS(rule,offset,selRange){var tree=require('cssEditTree').parse(rule,{offset:offset});var range=tree.nameRange(true);if(selRange.endrange.start){return range;}}return curRange;}var actions=require('actions'); +actions.add('select_next_item',function(editor){if(editor.getSyntax()=='css')return findNextCSSItem(editor);else return findNextHTMLItem(editor);});actions.add('select_previous_item',function(editor){if(editor.getSyntax()=='css')return findPrevCSSItem(editor);else return findPrevHTMLItem(editor);});});emmet.exec(function(require,_){var actions=require('actions');var matcher=require('htmlMatcher');var lastMatch=null;function matchPair(editor,direction){direction=String((direction||'out').toLowerCase());var info=require('editorUtils').outputInfo(editor);var range=require('range');var sel=range.create(editor.getSelectionRange());var content=info.content;if(lastMatch&&!lastMatch.range.equal(sel)){lastMatch=null;}if(lastMatch&&sel.length()){if(direction=='in'){if(lastMatch.type=='tag'&&!lastMatch.close){return false;}else{if(lastMatch.range.equal(lastMatch.outerRange)){lastMatch.range=lastMatch.innerRange;}else{var narrowed=require('utils').narrowToNonSpace(content,lastMatch.innerRange); +lastMatch=matcher.find(content,narrowed.start+1);if(lastMatch&&lastMatch.range.equal(sel)&&lastMatch.outerRange.equal(sel)){lastMatch.range=lastMatch.innerRange;}}}}else{if(!lastMatch.innerRange.equal(lastMatch.outerRange)&&lastMatch.range.equal(lastMatch.innerRange)&&sel.equal(lastMatch.range)){lastMatch.range=lastMatch.outerRange;}else{lastMatch=matcher.find(content,sel.start);if(lastMatch&&lastMatch.range.equal(sel)&&lastMatch.innerRange.equal(sel)){lastMatch.range=lastMatch.outerRange;}}}}else{lastMatch=matcher.find(content,sel.start);}if(lastMatch&&!lastMatch.range.equal(sel)){editor.createSelection(lastMatch.range.start,lastMatch.range.end);return true;}lastMatch=null;return false;}actions.add('match_pair',matchPair,{hidden:true});actions.add('match_pair_inward',function(editor){return matchPair(editor,'in');},{label:'HTML/Match Pair Tag (inward)'});actions.add('match_pair_outward',function(editor){return matchPair(editor,'out');},{label:'HTML/Match Pair Tag (outward)'});actions.add('matching_pair',function(editor){ +var content=String(editor.getContent());var caretPos=editor.getCaretPos();if(content.charAt(caretPos)=='<')caretPos++;var tag=matcher.tag(content,caretPos);if(tag&&tag.close){if(tag.open.range.inside(caretPos)){editor.setCaretPos(tag.close.range.start);}else{editor.setCaretPos(tag.open.range.start);}return true;}return false;},{label:'HTML/Go To Matching Tag Pair'});});emmet.exec(function(require,_){require('actions').add('remove_tag',function(editor){var utils=require('utils');var info=require('editorUtils').outputInfo(editor);var tag=require('htmlMatcher').tag(info.content,editor.getCaretPos());if(tag){if(!tag.close){editor.replaceContent(utils.getCaretPlaceholder(),tag.range.start,tag.range.end);}else{var tagContentRange=utils.narrowToNonSpace(info.content,tag.innerRange);var startLineBounds=utils.findNewlineBounds(info.content,tagContentRange.start);var startLinePad=utils.getLinePadding(startLineBounds.substring(info.content));var tagContent=tagContentRange.substring(info.content); +tagContent=utils.unindentString(tagContent,startLinePad);editor.replaceContent(utils.getCaretPlaceholder()+utils.escapeText(tagContent),tag.outerRange.start,tag.outerRange.end);}return true;}return false;},{label:'HTML/Remove Tag'});});emmet.exec(function(require,_){function joinTag(editor,profile,tag){var utils=require('utils');var slash=profile.selfClosing()||' /';var content=tag.open.range.substring(tag.source).replace(/\s*>$/,slash+'>');var caretPos=editor.getCaretPos();if(content.length+tag.outerRange.start$/,'>'); +caretPos=tag.outerRange.start+content.length;content+=tagContent+'';content=utils.escapeText(content);editor.replaceContent(content,tag.outerRange.start,tag.outerRange.end);editor.setCaretPos(caretPos);return true;}require('actions').add('split_join_tag',function(editor,profileName){var matcher=require('htmlMatcher');var info=require('editorUtils').outputInfo(editor,null,profileName);var profile=require('profile').get(info.profile);var tag=matcher.tag(info.content,editor.getCaretPos());if(tag){return tag.close?joinTag(editor,profile,tag):splitTag(editor,profile,tag);}return false;},{label:'HTML/Split\\Join Tag Declaration'});});emmet.define('reflectCSSValue',function(require,_){var handlers=require('handlerList').create();require('actions').add('reflect_css_value',function(editor){if(editor.getSyntax()!='css')return false;return require('actionUtils').compoundUpdate(editor,doCSSReflection(editor));},{label:'CSS/Reflect Value'});function doCSSReflection(editor){var cssEditTree=require('cssEditTree'); +var outputInfo=require('editorUtils').outputInfo(editor);var caretPos=editor.getCaretPos();var cssRule=cssEditTree.parseFromPosition(outputInfo.content,caretPos);if(!cssRule)return;var property=cssRule.itemFromPosition(caretPos,true);if(!property)return;var oldRule=cssRule.source;var offset=cssRule.options.offset;var caretDelta=caretPos-offset-property.range().start;handlers.exec(false,[property]);if(oldRule!==cssRule.source){return{data:cssRule.source,start:offset,end:offset+oldRule.length,caret:offset+property.range().start+caretDelta};}}function getReflectedCSSName(name){name=require('cssEditTree').baseName(name);var vendorPrefix='^(?:\\-\\w+\\-)?',m;if(name=='opacity'||name=='filter'){return new RegExp(vendorPrefix+'(?:opacity|filter)$');}else if(m=name.match(/^border-radius-(top|bottom)(left|right)/)){return new RegExp(vendorPrefix+'(?:'+name+'|border-'+m[1]+'-'+m[2]+'-radius)$');}else if(m=name.match(/^border-(top|bottom)-(left|right)-radius/)){return new RegExp(vendorPrefix+'(?:'+name+'|border-radius-'+m[1]+m[2]+')$'); +}return new RegExp(vendorPrefix+name+'$');}function reflectValue(donor,receiver){var value=getReflectedValue(donor.name(),donor.value(),receiver.name(),receiver.value());receiver.value(value);}function getReflectedValue(curName,curValue,refName,refValue){var cssEditTree=require('cssEditTree');var utils=require('utils');curName=cssEditTree.baseName(curName);refName=cssEditTree.baseName(refName);if(curName=='opacity'&&refName=='filter'){return refValue.replace(/opacity=[^)]*/i,'opacity='+Math.floor(parseFloat(curValue)*100));}else if(curName=='filter'&&refName=='opacity'){var m=curValue.match(/opacity=([^)]*)/i);return m?utils.prettifyNumber(parseInt(m[1])/100):refValue;}return curValue;}handlers.add(function(property){var reName=getReflectedCSSName(property.name());_.each(property.parent.list(),function(p){if(reName.test(p.name())){reflectValue(property,p);}});},{order:-1});return{addHandler:function(fn,options){handlers.add(fn,options);},removeHandler:function(fn){handlers.remove(fn,options); +}};});emmet.exec(function(require,_){require('actions').add('evaluate_math_expression',function(editor){var actionUtils=require('actionUtils');var utils=require('utils');var content=String(editor.getContent());var chars='.+-*/\\';var sel=require('range').create(editor.getSelectionRange());if(!sel.length()){sel=actionUtils.findExpressionBounds(editor,function(ch){return utils.isNumeric(ch)||chars.indexOf(ch)!=-1;});}if(sel&&sel.length()){var expr=sel.substring(content);expr=expr.replace(/([\d\.\-]+)\\([\d\.\-]+)/g,'Math.round($1/$2)');try{var result=utils.prettifyNumber(new Function('return '+expr)());editor.replaceContent(result,sel.start,sel.end);editor.setCaretPos(sel.start+result.length);return true;}catch(e){}}return false;},{label:'Numbers/Evaluate Math Expression'});});emmet.exec(function(require,_){function incrementNumber(editor,step){var utils=require('utils');var actionUtils=require('actionUtils');var hasSign=false;var hasDecimal=false;var r=actionUtils.findExpressionBounds(editor,function(ch,pos,content){ +if(utils.isNumeric(ch))return true;if(ch=='.'){if(!utils.isNumeric(content.charAt(pos+1)))return false;return hasDecimal?false:hasDecimal=true;}if(ch=='-')return hasSign?false:hasSign=true;return false;});if(r&&r.length()){var strNum=r.substring(String(editor.getContent()));var num=parseFloat(strNum);if(!_.isNaN(num)){num=utils.prettifyNumber(num+step);if(/^(\-?)0+[1-9]/.test(strNum)){var minus='';if(RegExp.$1){minus='-';num=num.substring(1);}var parts=num.split('.');parts[0]=utils.zeroPadString(parts[0],intLength(strNum));num=minus+parts.join('.');}editor.replaceContent(num,r.start,r.end);editor.createSelection(r.start,r.start+num.length);return true;}}return false;}function intLength(num){num=num.replace(/^\-/,'');if(~num.indexOf('.')){return num.split('.')[0].length;}return num.length;}var actions=require('actions');_.each([1,-1,10,-10,0.1,-0.1],function(num){var prefix=num>0?'increment':'decrement';actions.add(prefix+'_number_by_'+String(Math.abs(num)).replace('.','').substring(0,2),function(editor){ +return incrementNumber(editor,num);},{label:'Numbers/'+prefix.charAt(0).toUpperCase()+prefix.substring(1)+' number by '+Math.abs(num)});});});emmet.exec(function(require,_){var actions=require('actions');var prefs=require('preferences');prefs.define('css.closeBraceIndentation','\n','Indentation before closing brace of CSS rule. Some users prefere '+'indented closing brace of CSS rule for better readability. '+'This preference’s value will be automatically inserted before '+'closing brace when user adds newline in newly created CSS rule '+'(e.g. when “Insert formatted linebreak” action will be performed '+'in CSS file). If you’re such user, you may want to write put a value '+'like \\n\\t in this preference.');actions.add('insert_formatted_line_break_only',function(editor){var utils=require('utils');var res=require('resources');var info=require('editorUtils').outputInfo(editor);var caretPos=editor.getCaretPos();var nl=utils.getNewline();if(_.include(['html','xml','xsl'],info.syntax)){ +var pad=res.getVariable('indentation');var tag=require('htmlMatcher').tag(info.content,caretPos);if(tag&&!tag.innerRange.length()){editor.replaceContent(nl+pad+utils.getCaretPlaceholder()+nl,caretPos);return true;}}else if(info.syntax=='css'){var content=info.content;if(caretPos&&content.charAt(caretPos-1)=='{'){var append=prefs.get('css.closeBraceIndentation');var pad=res.getVariable('indentation');var hasCloseBrace=content.charAt(caretPos)=='}';if(!hasCloseBrace){for(var i=caretPos,il=content.length,ch;icurPadding.length)editor.replaceContent(nl+nextPadding,caretPos,caretPos,true);else editor.replaceContent(nl,caretPos);}return true;},{hidden:true});});emmet.exec(function(require,_){require('actions').add('merge_lines',function(editor){var matcher=require('htmlMatcher');var utils=require('utils');var editorUtils=require('editorUtils');var info=editorUtils.outputInfo(editor);var selection=require('range').create(editor.getSelectionRange());if(!selection.length()){var pair=matcher.find(info.content,editor.getCaretPos());if(pair){selection=pair.outerRange;}}if(selection.length()){var text=selection.substring(info.content);var lines=utils.splitByLines(text);for(var i=1;i=0){if(startsWith('src=',text,caretPos)){if(m=text.substr(caretPos).match(/^(src=(["'])?)([^'"<>\s]+)\1?/)){data=m[3];caretPos+=m[1].length;}break;}else if(startsWith('url(',text,caretPos)){if(m=text.substr(caretPos).match(/^(url\((['"])?)([^'"\)\s]+)\1?/)){data=m[3];caretPos+=m[1].length;}break;}}}if(data){if(startsWith('data:',data))return decodeFromBase64(editor,data,caretPos);else return encodeToBase64(editor,data,caretPos);}return false;},{label:'Encode\\Decode data:URL image'});function startsWith(token,text,pos){ +pos=pos||0;return text.charAt(pos)==token.charAt(0)&&text.substr(pos,token.length)==token;}function encodeToBase64(editor,imgPath,pos){var file=require('file');var actionUtils=require('actionUtils');var editorFile=editor.getFilePath();var defaultMimeType='application/octet-stream';if(editorFile===null){throw"You should save your file before using this action";}var realImgPath=file.locateFile(editorFile,imgPath);if(realImgPath===null){throw"Can't find "+imgPath+' file';}file.read(realImgPath,function(err,content){if(err){throw'Unable to read '+realImgPath+': '+err;}var b64=require('base64').encode(String(content));if(!b64){throw"Can't encode file content to base64";}b64='data:'+(actionUtils.mimeTypes[String(file.getExt(realImgPath))]||defaultMimeType)+';base64,'+b64;editor.replaceContent('$0'+b64,pos,pos+imgPath.length);});return true;}function decodeFromBase64(editor,data,pos){var filePath=String(editor.prompt('Enter path to file (absolute or relative)'));if(!filePath)return false;var file=require('file'); +var absPath=file.createPath(editor.getFilePath(),filePath);if(!absPath){throw"Can't save file";}file.save(absPath,require('base64').decode(data.replace(/^data\:.+?;.+?,/,'')));editor.replaceContent('$0'+filePath,pos,pos+data.length);return true;}});emmet.exec(function(require,_){function updateImageSizeHTML(editor){var offset=editor.getCaretPos();var info=require('editorUtils').outputInfo(editor);var xmlElem=require('xmlEditTree').parseFromPosition(info.content,offset,true);if(xmlElem&&(xmlElem.name()||'').toLowerCase()=='img'){getImageSizeForSource(editor,xmlElem.value('src'),function(size){if(size){var compoundData=xmlElem.range(true);xmlElem.value('width',size.width);xmlElem.value('height',size.height,xmlElem.indexOf('width')+1);require('actionUtils').compoundUpdate(editor,_.extend(compoundData,{data:xmlElem.toString(),caret:offset}));}});}}function updateImageSizeCSS(editor){var offset=editor.getCaretPos();var info=require('editorUtils').outputInfo(editor);var cssRule=require('cssEditTree').parseFromPosition(info.content,offset,true); +if(cssRule){var prop=cssRule.itemFromPosition(offset,true),m;if(prop&&(m=/url\((["']?)(.+?)\1\)/i.exec(prop.value()||''))){getImageSizeForSource(editor,m[2],function(size){if(size){var compoundData=cssRule.range(true);cssRule.value('width',size.width+'px');cssRule.value('height',size.height+'px',cssRule.indexOf('width')+1);require('actionUtils').compoundUpdate(editor,_.extend(compoundData,{data:cssRule.toString(),caret:offset}));}});}}}function getImageSizeForSource(editor,src,callback){var fileContent;var au=require('actionUtils');if(src){if(/^data:/.test(src)){fileContent=require('base64').decode(src.replace(/^data\:.+?;.+?,/,''));return callback(au.getImageSize(fileContent));}var file=require('file');var absPath=file.locateFile(editor.getFilePath(),src);if(absPath===null){throw"Can't find "+src+' file';}file.read(absPath,function(err,content){if(err){throw'Unable to read '+absPath+': '+err;}content=String(content);callback(au.getImageSize(content));});}}require('actions').add('update_image_size',function(editor){ +if(_.include(['css','less','scss'],String(editor.getSyntax()))){updateImageSizeCSS(editor);}else{updateImageSizeHTML(editor);}return true;});});emmet.define('cssResolver',function(require,_){var module=null;var prefixObj={prefix:'emmet',obsolete:false,transformName:function(name){return'-'+this.prefix+'-'+name;},properties:function(){return getProperties('css.'+this.prefix+'Properties')||[];},supports:function(name){return _.include(this.properties(),name);}};var vendorPrefixes={};var defaultValue='${1};';var prefs=require('preferences');prefs.define('css.valueSeparator',': ','Defines a symbol that should be placed between CSS property and '+'value when expanding CSS abbreviations.');prefs.define('css.propertyEnd',';','Defines a symbol that should be placed at the end of CSS property '+'when expanding CSS abbreviations.');prefs.define('stylus.valueSeparator',' ','Defines a symbol that should be placed between CSS property and '+'value when expanding CSS abbreviations in Stylus dialect.'); +prefs.define('stylus.propertyEnd','','Defines a symbol that should be placed at the end of CSS property '+'when expanding CSS abbreviations in Stylus dialect.');prefs.define('sass.propertyEnd','','Defines a symbol that should be placed at the end of CSS property '+'when expanding CSS abbreviations in SASS dialect.');prefs.define('css.autoInsertVendorPrefixes',true,'Automatically generate vendor-prefixed copies of expanded CSS '+'property. By default, Emmet will generate vendor-prefixed '+'properties only when you put dash before abbreviation '+'(e.g. -bxsh). With this option enabled, you don’t '+'need dashes before abbreviations: Emmet will produce '+'vendor-prefixed properties for you.');var descTemplate=_.template('A comma-separated list of CSS properties that may have '+'<%= vendor %> vendor prefix. This list is used to generate '+'a list of prefixed properties when expanding -property '+'abbreviations. Empty list means that all possible CSS values may ' ++'have <%= vendor %> prefix.');var descAddonTemplate=_.template('A comma-separated list of additional CSS properties '+'for css.<%= vendor %>Preperties preference. '+'You should use this list if you want to add or remove a few CSS '+'properties to original set. To add a new property, simply write its name, '+'to remove it, precede property with hyphen.
'+'For example, to add foo property and remove border-radius one, '+'the preference value will look like this: foo, -border-radius.');var props={'webkit':'animation, animation-delay, animation-direction, animation-duration, animation-fill-mode, animation-iteration-count, animation-name, animation-play-state, animation-timing-function, appearance, backface-visibility, background-clip, background-composite, background-origin, background-size, border-fit, border-horizontal-spacing, border-image, border-vertical-spacing, box-align, box-direction, box-flex, box-flex-group, box-lines, box-ordinal-group, box-orient, box-pack, box-reflect, box-shadow, color-correction, column-break-after, column-break-before, column-break-inside, column-count, column-gap, column-rule-color, column-rule-style, column-rule-width, column-span, column-width, dashboard-region, font-smoothing, highlight, hyphenate-character, hyphenate-limit-after, hyphenate-limit-before, hyphens, line-box-contain, line-break, line-clamp, locale, margin-before-collapse, margin-after-collapse, marquee-direction, marquee-increment, marquee-repetition, marquee-style, mask-attachment, mask-box-image, mask-box-image-outset, mask-box-image-repeat, mask-box-image-slice, mask-box-image-source, mask-box-image-width, mask-clip, mask-composite, mask-image, mask-origin, mask-position, mask-repeat, mask-size, nbsp-mode, perspective, perspective-origin, rtl-ordering, text-combine, text-decorations-in-effect, text-emphasis-color, text-emphasis-position, text-emphasis-style, text-fill-color, text-orientation, text-security, text-stroke-color, text-stroke-width, transform, transition, transform-origin, transform-style, transition-delay, transition-duration, transition-property, transition-timing-function, user-drag, user-modify, user-select, writing-mode, svg-shadow, box-sizing, border-radius', +'moz':'animation-delay, animation-direction, animation-duration, animation-fill-mode, animation-iteration-count, animation-name, animation-play-state, animation-timing-function, appearance, backface-visibility, background-inline-policy, binding, border-bottom-colors, border-image, border-left-colors, border-right-colors, border-top-colors, box-align, box-direction, box-flex, box-ordinal-group, box-orient, box-pack, box-shadow, box-sizing, column-count, column-gap, column-rule-color, column-rule-style, column-rule-width, column-width, float-edge, font-feature-settings, font-language-override, force-broken-image-icon, hyphens, image-region, orient, outline-radius-bottomleft, outline-radius-bottomright, outline-radius-topleft, outline-radius-topright, perspective, perspective-origin, stack-sizing, tab-size, text-blink, text-decoration-color, text-decoration-line, text-decoration-style, text-size-adjust, transform, transform-origin, transform-style, transition, transition-delay, transition-duration, transition-property, transition-timing-function, user-focus, user-input, user-modify, user-select, window-shadow, background-clip, border-radius', +'ms':'accelerator, backface-visibility, background-position-x, background-position-y, behavior, block-progression, box-align, box-direction, box-flex, box-line-progression, box-lines, box-ordinal-group, box-orient, box-pack, content-zoom-boundary, content-zoom-boundary-max, content-zoom-boundary-min, content-zoom-chaining, content-zoom-snap, content-zoom-snap-points, content-zoom-snap-type, content-zooming, filter, flow-from, flow-into, font-feature-settings, grid-column, grid-column-align, grid-column-span, grid-columns, grid-layer, grid-row, grid-row-align, grid-row-span, grid-rows, high-contrast-adjust, hyphenate-limit-chars, hyphenate-limit-lines, hyphenate-limit-zone, hyphens, ime-mode, interpolation-mode, layout-flow, layout-grid, layout-grid-char, layout-grid-line, layout-grid-mode, layout-grid-type, line-break, overflow-style, perspective, perspective-origin, perspective-origin-x, perspective-origin-y, scroll-boundary, scroll-boundary-bottom, scroll-boundary-left, scroll-boundary-right, scroll-boundary-top, scroll-chaining, scroll-rails, scroll-snap-points-x, scroll-snap-points-y, scroll-snap-type, scroll-snap-x, scroll-snap-y, scrollbar-arrow-color, scrollbar-base-color, scrollbar-darkshadow-color, scrollbar-face-color, scrollbar-highlight-color, scrollbar-shadow-color, scrollbar-track-color, text-align-last, text-autospace, text-justify, text-kashida-space, text-overflow, text-size-adjust, text-underline-position, touch-action, transform, transform-origin, transform-origin-x, transform-origin-y, transform-origin-z, transform-style, transition, transition-delay, transition-duration, transition-property, transition-timing-function, user-select, word-break, word-wrap, wrap-flow, wrap-margin, wrap-through, writing-mode', +'o':'dashboard-region, animation, animation-delay, animation-direction, animation-duration, animation-fill-mode, animation-iteration-count, animation-name, animation-play-state, animation-timing-function, border-image, link, link-source, object-fit, object-position, tab-size, table-baseline, transform, transform-origin, transition, transition-delay, transition-duration, transition-property, transition-timing-function, accesskey, input-format, input-required, marquee-dir, marquee-loop, marquee-speed, marquee-style'};_.each(props,function(v,k){prefs.define('css.'+k+'Properties',v,descTemplate({vendor:k}));prefs.define('css.'+k+'PropertiesAddon','',descAddonTemplate({vendor:k}));});prefs.define('css.unitlessProperties','z-index, line-height, opacity, font-weight, zoom','The list of properties whose values ​​must not contain units.');prefs.define('css.intUnit','px','Default unit for integer values');prefs.define('css.floatUnit','em','Default unit for float values');prefs.define('css.keywords','auto, inherit', +'A comma-separated list of valid keywords that can be used in CSS abbreviations.');prefs.define('css.keywordAliases','a:auto, i:inherit, s:solid, da:dashed, do:dotted, t:transparent','A comma-separated list of keyword aliases, used in CSS abbreviation. '+'Each alias should be defined as alias:keyword_name.');prefs.define('css.unitAliases','e:em, p:%, x:ex, r:rem','A comma-separated list of unit aliases, used in CSS abbreviation. '+'Each alias should be defined as alias:unit_value.');prefs.define('css.color.short',true,'Should color values like #ffffff be shortened to '+'#fff after abbreviation with color was expanded.');prefs.define('css.color.case','keep','Letter case of color values generated by abbreviations with color '+'(like c#0). Possible values are upper, '+'lower and keep.');prefs.define('css.fuzzySearch',true, +'Enable fuzzy search among CSS snippet names. When enabled, every '+'unknown snippet will be scored against available snippet '+'names (not values or CSS properties!). The match with best score '+'will be used to resolve snippet value. For example, with this '+'preference enabled, the following abbreviations are equal: '+'ov:h == ov-h == o-h == '+'oh');prefs.define('css.fuzzySearchMinScore',0.3,'The minium score (from 0 to 1) that fuzzy-matched abbreviation should '+'achive. Lower values may produce many false-positive matches, '+'higher values may reduce possible matches.');prefs.define('css.alignVendor',false,'If set to true, all generated vendor-prefixed properties '+'will be aligned by real property name.');function isNumeric(ch){var code=ch&&ch.charCodeAt(0);return(ch&&ch=='.'||(code>47&&code<58));}function isSingleProperty(snippet){var utils=require('utils');snippet=utils.trim(snippet);if(~snippet.indexOf('/*')||/[\n\r]/.test(snippet)){ +return false;}if(!/^[a-z0-9\-]+\s*\:/i.test(snippet)){return false;}snippet=require('tabStops').processText(snippet,{replaceCarets:true,tabstop:function(){return'value';}});return snippet.split(':').length==2;}function normalizeValue(value){if(value.charAt(0)=='-'&&!/^\-[\.\d]/.test(value)){value=value.replace(/^\-+/,'');}if(value.charAt(0)=='#'){return normalizeHexColor(value);}return getKeyword(value);}function normalizeHexColor(value){var hex=value.replace(/^#+/,'')||'0';if(hex.toLowerCase()=='t'){return'transparent';}var repeat=require('utils').repeatString;var color=null;switch(hex.length){case 1:color=repeat(hex,6);break;case 2:color=repeat(hex,3);break;case 3:color=hex.charAt(0)+hex.charAt(0)+hex.charAt(1)+hex.charAt(1)+hex.charAt(2)+hex.charAt(2);break;case 4:color=hex+hex.substr(0,2);break;case 5:color=hex+hex.charAt(0);break;default:color=hex.substr(0,6);}if(prefs.get('css.color.short')){var p=color.split('');if(p[0]==p[1]&&p[2]==p[3]&&p[4]==p[5]){color=p[0]+p[2]+p[4];}} +switch(prefs.get('css.color.case')){case'upper':color=color.toUpperCase();break;case'lower':color=color.toLowerCase();break;}return'#'+color;}function getKeyword(name){var aliases=prefs.getDict('css.keywordAliases');return name in aliases?aliases[name]:name;}function getUnit(name){var aliases=prefs.getDict('css.unitAliases');return name in aliases?aliases[name]:name;}function isValidKeyword(keyword){return _.include(prefs.getArray('css.keywords'),getKeyword(keyword));}function hasPrefix(property,prefix){var info=vendorPrefixes[prefix];if(!info)info=_.find(vendorPrefixes,function(data){return data.prefix==prefix;});return info&&info.supports(property);}function findPrefixes(property,noAutofill){var result=[];_.each(vendorPrefixes,function(obj,prefix){if(hasPrefix(property,prefix)){result.push(prefix);}});if(!result.length&&!noAutofill){_.each(vendorPrefixes,function(obj,prefix){if(!obj.obsolete)result.push(prefix);});}return result;}function addPrefix(name,obj){if(_.isString(obj))obj={prefix:obj}; +vendorPrefixes[name]=_.extend({},prefixObj,obj);}function getSyntaxPreference(name,syntax){if(syntax){var val=prefs.get(syntax+'.'+name);if(!_.isUndefined(val))return val;}return prefs.get('css.'+name);}function formatProperty(property,syntax){var ix=property.indexOf(':');property=property.substring(0,ix).replace(/\s+$/,'')+getSyntaxPreference('valueSeparator',syntax)+require('utils').trim(property.substring(ix+1));return property.replace(/\s*;\s*$/,getSyntaxPreference('propertyEnd',syntax));}function transformSnippet(snippet,isImportant,syntax){if(!_.isString(snippet))snippet=snippet.data;if(!isSingleProperty(snippet))return snippet;if(isImportant){if(~snippet.indexOf(';')){snippet=snippet.split(';').join(' !important;');}else{snippet+=' !important';}}return formatProperty(snippet,syntax);}function parseList(list){var result=_.map((list||'').split(','),require('utils').trim);return result.length?result:null;}function getProperties(key){var list=prefs.getArray(key);_.each(prefs.getArray(key+'Addon'),function(prop){ +if(prop.charAt(0)=='-'){list=_.without(list,prop.substr(1));}else{if(prop.charAt(0)=='+')prop=prop.substr(1);list.push(prop);}});return list;}addPrefix('w',{prefix:'webkit'});addPrefix('m',{prefix:'moz'});addPrefix('s',{prefix:'ms'});addPrefix('o',{prefix:'o'});var cssSyntaxes=['css','less','sass','scss','stylus'];require('resources').addResolver(function(node,syntax){if(_.include(cssSyntaxes,syntax)&&node.isElement()){return module.expandToSnippet(node.abbreviation,syntax);}return null;});var ea=require('expandAbbreviation');ea.addHandler(function(editor,syntax,profile){if(!_.include(cssSyntaxes,syntax)){return false;}var caretPos=editor.getSelectionRange().end;var abbr=ea.findAbbreviation(editor);if(abbr){var content=emmet.expandAbbreviation(abbr,syntax,profile);if(content){var replaceFrom=caretPos-abbr.length;var replaceTo=caretPos;if(editor.getContent().charAt(caretPos)==';'&&content.charAt(content.length-1)==';'){replaceTo++;}editor.replaceContent(content,replaceFrom,replaceTo); +return true;}}return false;});return module={addPrefix:addPrefix,supportsPrefix:hasPrefix,prefixed:function(property,prefix){return hasPrefix(property,prefix)?'-'+prefix+'-'+property:property;},listPrefixes:function(){return _.map(vendorPrefixes,function(obj){return obj.prefix;});},getPrefix:function(name){return vendorPrefixes[name];},removePrefix:function(name){if(name in vendorPrefixes)delete vendorPrefixes[name];},extractPrefixes:function(abbr){if(abbr.charAt(0)!='-'){return{property:abbr,prefixes:null};}var i=1,il=abbr.length,ch;var prefixes=[];while(ibackground-color property with gradient first color '+'as fallback for old browsers.');function normalizeSpace(str){return require('utils').trim(str).replace(/\s+/g,' ');} +function parseLinearGradient(gradient){var direction=defaultLinearDirections[0];var stream=require('stringStream').create(require('utils').trim(gradient));var colorStops=[],ch;while(ch=stream.next()){if(stream.peek()==','){colorStops.push(stream.current());stream.next();stream.eatSpace();stream.start=stream.pos;}else if(ch=='('){stream.skipTo(')');}}colorStops.push(stream.current());colorStops=_.compact(_.map(colorStops,normalizeSpace));if(!colorStops.length)return null;if(reDeg.test(colorStops[0])||reKeyword.test(colorStops[0])){direction=colorStops.shift();}return{type:'linear',direction:direction,colorStops:_.map(colorStops,parseColorStop)};}function parseColorStop(colorStop){colorStop=normalizeSpace(colorStop);var color=null;colorStop=colorStop.replace(/^(\w+\(.+?\))\s*/,function(str,c){color=c;return'';});if(!color){var parts=colorStop.split(' ');color=parts[0];colorStop=parts[1]||'';}var result={color:color};if(colorStop){colorStop.replace(/^(\-?[\d\.]+)([a-z%]+)?$/,function(str,pos,unit){ +result.position=pos;if(~pos.indexOf('.')){unit='';}else if(!unit){unit='%';}if(unit)result.unit=unit;});}return result;}function resolvePropertyName(name,syntax){var res=require('resources');var prefs=require('preferences');var snippet=res.findSnippet(syntax,name);if(!snippet&&prefs.get('css.fuzzySearch')){snippet=res.fuzzyFindSnippet(syntax,name,parseFloat(prefs.get('css.fuzzySearchMinScore')));}if(snippet){if(!_.isString(snippet)){snippet=snippet.data;}return require('cssResolver').splitSnippet(snippet).name;}}function fillImpliedPositions(colorStops){var from=0;_.each(colorStops,function(cs,i){if(!i)return cs.position=cs.position||0;if(i==colorStops.length-1&&!('position'in cs))cs.position=1;if('position'in cs){var start=colorStops[from].position||0;var step=(cs.position-start)/(i-from);_.each(colorStops.slice(from,i),function(cs2,j){cs2.position=start+step*j;});from=i;}});}function textualDirection(direction){var angle=parseFloat(direction);if(!_.isNaN(angle)){switch(angle%360){ +case 0:return'left';case 90:return'bottom';case 180:return'right';case 240:return'top';}}return direction;}function oldWebkitDirection(direction){direction=textualDirection(direction);if(reDeg.test(direction))throw"The direction is an angle that can’t be converted.";var v=function(pos){return~direction.indexOf(pos)?'100%':'0';};return v('right')+' '+v('bottom')+', '+v('left')+' '+v('top');}function getPrefixedNames(name){var prefixes=prefs.getArray('css.gradient.prefixes');var names=prefixes?_.map(prefixes,function(p){return'-'+p+'-'+name;}):[];names.push(name);return names;}function getPropertiesForGradient(gradient,propertyName){var props=[];var css=require('cssResolver');if(prefs.get('css.gradient.fallback')&&~propertyName.toLowerCase().indexOf('background')){props.push({name:'background-color',value:'${1:'+gradient.colorStops[0].color+'}'});}_.each(prefs.getArray('css.gradient.prefixes'),function(prefix){var name=css.prefixed(propertyName,prefix);if(prefix=='webkit'&&prefs.get('css.gradient.oldWebkit')){ +try{props.push({name:name,value:module.oldWebkitLinearGradient(gradient)});}catch(e){}}props.push({name:name,value:module.toString(gradient,prefix)});});return props.sort(function(a,b){return b.name.length-a.name.length;});}function pasteGradient(property,gradient,valueRange){var rule=property.parent;var utils=require('utils');var alignVendor=require('preferences').get('css.alignVendor');var sep=property.styleSeparator;var before=property.styleBefore;_.each(rule.getAll(getPrefixedNames(property.name())),function(item){if(item!=property&&/gradient/i.test(item.value())){if(item.styleSeparator.length<%= attr("class", ".") %> -->','A definition of comment that should be placed after matched '+'element when comment filter is applied. This definition ' ++'is an ERB-style template passed to _.template() '+'function (see Underscore.js docs for details). In template context, '+'the following properties and functions are availabe:\n'+'
    '+'
  • attr(name, before, after) – a function that outputs'+'specified attribute value concatenated with before '+'and after strings. If attribute doesn\'t exists, the '+'empty string will be returned.
  • '+'
  • node – current node (instance of AbbreviationNode)
  • '+'
  • name – name of current tag
  • '+'
  • padding – current string padding, can be used '+'for formatting
  • '+'
');prefs.define('filter.commentBefore','','A definition of comment that should be placed before matched '+'element when comment filter is applied. '+'For more info, read description of filter.commentAfter '+'property');prefs.define('filter.commentTrigger','id, class', +'A comma-separated list of attribute names that should exist in abbreviatoin '+'where comment should be added. If you wish to add comment for '+'every element, set this option to *');function addComments(node,templateBefore,templateAfter){var utils=require('utils');var trigger=prefs.get('filter.commentTrigger');if(trigger!='*'){var shouldAdd=_.find(trigger.split(','),function(name){return!!node.attribute(utils.trim(name));});if(!shouldAdd)return;}var ctx={node:node,name:node.name(),padding:node.parent?node.parent.padding:'',attr:function(name,before,after){var attr=node.attribute(name);if(attr){return(before||'')+attr+(after||'');}return'';}};var nodeBefore=utils.normalizeNewline(templateBefore?templateBefore(ctx):'');var nodeAfter=utils.normalizeNewline(templateAfter?templateAfter(ctx):'');node.start=node.start.replace(//,'>'+nodeAfter);}function process(tree,before,after){var abbrUtils=require('abbreviationUtils');_.each(tree.children,function(item){ +if(abbrUtils.isBlock(item))addComments(item,before,after);process(item,before,after);});return tree;}require('filters').add('c',function(tree){var templateBefore=_.template(prefs.get('filter.commentBefore'));var templateAfter=_.template(prefs.get('filter.commentAfter'));return process(tree,templateBefore,templateAfter);});});emmet.exec(function(require,_){var charMap={'<':'<','>':'>','&':'&'};function escapeChars(str){return str.replace(/([<>&])/g,function(str,p1){return charMap[p1];});}require('filters').add('e',function process(tree){_.each(tree.children,function(item){item.start=escapeChars(item.start);item.end=escapeChars(item.end);item.content=escapeChars(item.content);process(item);});return tree;});});emmet.exec(function(require,_){var placeholder='%s';var prefs=require('preferences');prefs.define('format.noIndentTags','html','A comma-separated list of tag names that should not get inner indentation.');prefs.define('format.forceIndentationForTags','body', +'A comma-separated list of tag names that should always get inner indentation.');function getIndentation(node){if(_.include(prefs.getArray('format.noIndentTags')||[],node.name())){return'';}return require('resources').getVariable('indentation');}function hasBlockSibling(item){return item.parent&&require('abbreviationUtils').hasBlockChildren(item.parent);}function isVeryFirstChild(item){return item.parent&&!item.parent.parent&&!item.index();}function shouldAddLineBreak(node,profile){var abbrUtils=require('abbreviationUtils');if(profile.tag_nl===true||abbrUtils.isBlock(node))return true;if(!node.parent||!profile.inline_break)return false;return shouldFormatInline(node.parent,profile);}function shouldBreakChild(node,profile){return node.children.length&&shouldAddLineBreak(node.children[0],profile);}function shouldFormatInline(node,profile){var nodeCount=0;var abbrUtils=require('abbreviationUtils');return!!_.find(node.children,function(child){if(child.isTextNode()||!abbrUtils.isInline(child)) +nodeCount=0;else if(abbrUtils.isInline(child))nodeCount++;if(nodeCount>=profile.inline_break)return true;});}function isRoot(item){return!item.parent;}function processSnippet(item,profile,level){item.start=item.end='';if(!isVeryFirstChild(item)&&profile.tag_nl!==false&&shouldAddLineBreak(item,profile)){if(isRoot(item.parent)||!require('abbreviationUtils').isInline(item.parent)){item.start=require('utils').getNewline()+item.start;}}return item;}function shouldBreakInsideInline(node,profile){var abbrUtils=require('abbreviationUtils');var hasBlockElems=_.any(node.children,function(child){if(abbrUtils.isSnippet(child))return false;return!abbrUtils.isInline(child);});if(!hasBlockElems){return shouldFormatInline(node,profile);}return true;}function processTag(item,profile,level){item.start=item.end=placeholder;var utils=require('utils');var abbrUtils=require('abbreviationUtils');var isUnary=abbrUtils.isUnary(item);var nl=utils.getNewline();var indent=getIndentation(item);if(profile.tag_nl!==false){ +var forceNl=profile.tag_nl===true&&(profile.tag_nl_leaf||item.children.length);if(!forceNl){forceNl=_.include(prefs.getArray('format.forceIndentationForTags')||[],item.name());}if(!item.isTextNode()){if(shouldAddLineBreak(item,profile)){if(!isVeryFirstChild(item)&&(!abbrUtils.isSnippet(item.parent)||item.index()))item.start=nl+item.start;if(abbrUtils.hasBlockChildren(item)||shouldBreakChild(item,profile)||(forceNl&&!isUnary))item.end=nl+item.end;if(abbrUtils.hasTagsInContent(item)||(forceNl&&!item.children.length&&!isUnary))item.start+=nl+indent;}else if(abbrUtils.isInline(item)&&hasBlockSibling(item)&&!isVeryFirstChild(item)){item.start=nl+item.start;}else if(abbrUtils.isInline(item)&&shouldBreakInsideInline(item,profile)){item.end=nl+item.end;}item.padding=indent;}}return item;}require('filters').add('_format',function process(tree,profile,level){level=level||0;var abbrUtils=require('abbreviationUtils');_.each(tree.children,function(item){if(abbrUtils.isSnippet(item))processSnippet(item,profile,level); +else processTag(item,profile,level);process(item,profile,level+1);});return tree;});});emmet.exec(function(require,_){var childToken='${child}';function transformClassName(className){return require('utils').trim(className).replace(/\s+/g,'.');}function makeAttributesString(tag,profile){var attrs='';var otherAttrs=[];var attrQuote=profile.attributeQuote();var cursor=profile.cursor();_.each(tag.attributeList(),function(a){var attrName=profile.attributeName(a.name);switch(attrName.toLowerCase()){case'id':attrs+='#'+(a.value||cursor);break;case'class':attrs+='.'+transformClassName(a.value||cursor);break;default:otherAttrs.push(':'+attrName+' => '+attrQuote+(a.value||cursor)+attrQuote);}});if(otherAttrs.length)attrs+='{'+otherAttrs.join(', ')+'}';return attrs;}function hasBlockSibling(item){return item.parent&&item.parent.hasBlockChildren();}function processTag(item,profile,level){if(!item.parent)return item;var abbrUtils=require('abbreviationUtils');var utils=require('utils');var attrs=makeAttributesString(item,profile); +var cursor=profile.cursor();var isUnary=abbrUtils.isUnary(item);var selfClosing=profile.self_closing_tag&&isUnary?'/':'';var start='';var tagName='%'+profile.tagName(item.name());if(tagName.toLowerCase()=='%div'&&attrs&&attrs.indexOf('{')==-1)tagName='';item.end='';start=tagName+attrs+selfClosing+' ';var placeholder='%s';item.start=utils.replaceSubstring(item.start,start,item.start.indexOf(placeholder),placeholder);if(!item.children.length&&!isUnary)item.start+=cursor;return item;}require('filters').add('haml',function process(tree,profile,level){level=level||0;var abbrUtils=require('abbreviationUtils');if(!level){tree=require('filters').apply(tree,'_format',profile);}_.each(tree.children,function(item){if(!abbrUtils.isSnippet(item))processTag(item,profile,level);process(item,profile,level+1);});return tree;});});emmet.exec(function(require,_){function makeAttributesString(node,profile){var attrQuote=profile.attributeQuote();var cursor=profile.cursor();return _.map(node.attributeList(),function(a){ +var attrName=profile.attributeName(a.name);return' '+attrName+'='+attrQuote+(a.value||cursor)+attrQuote;}).join('');}function processTag(item,profile,level){if(!item.parent)return item;var abbrUtils=require('abbreviationUtils');var utils=require('utils');var attrs=makeAttributesString(item,profile);var cursor=profile.cursor();var isUnary=abbrUtils.isUnary(item);var start='';var end='';if(!item.isTextNode()){var tagName=profile.tagName(item.name());if(isUnary){start='<'+tagName+attrs+profile.selfClosing()+'>';item.end='';}else{start='<'+tagName+attrs+'>';end='';}}var placeholder='%s';item.start=utils.replaceSubstring(item.start,start,item.start.indexOf(placeholder),placeholder);item.end=utils.replaceSubstring(item.end,end,item.end.indexOf(placeholder),placeholder);if(!item.children.length&&!isUnary&&!~item.content.indexOf(cursor)&&!require('tabStops').extract(item.content).tabstops.length){item.start+=cursor;}return item;}require('filters').add('html',function process(tree,profile,level){ +level=level||0;var abbrUtils=require('abbreviationUtils');if(!level){tree=require('filters').apply(tree,'_format',profile);}_.each(tree.children,function(item){if(!abbrUtils.isSnippet(item))processTag(item,profile,level);process(item,profile,level+1);});return tree;});});emmet.exec(function(require,_){var rePad=/^\s+/;var reNl=/[\n\r]/g;require('filters').add('s',function process(tree,profile,level){var abbrUtils=require('abbreviationUtils');_.each(tree.children,function(item){if(!abbrUtils.isSnippet(item)){item.start=item.start.replace(rePad,'');item.end=item.end.replace(rePad,'');}item.start=item.start.replace(reNl,'');item.end=item.end.replace(reNl,'');item.content=item.content.replace(reNl,'');process(item);});return tree;});});emmet.exec(function(require,_){require('preferences').define('filter.trimRegexp','[\\s|\\u00a0]*[\\d|#|\\-|\*|\\u2022]+\\.?\\s*','Regular expression used to remove list markers (numbers, dashes, '+'bullets, etc.) in t (trim) filter. The trim filter ' ++'is useful for wrapping with abbreviation lists, pased from other '+'documents (for example, Word documents).');function process(tree,re){_.each(tree.children,function(item){if(item.content)item.content=item.content.replace(re,'');process(item,re);});return tree;}require('filters').add('t',function(tree){var re=new RegExp(require('preferences').get('filter.trimRegexp'));return process(tree,re);});});emmet.exec(function(require,_){var tags={'xsl:variable':1,'xsl:with-param':1};function trimAttribute(node){node.start=node.start.replace(/\s+select\s*=\s*(['"]).*?\1/,'');}require('filters').add('xsl',function process(tree){var abbrUtils=require('abbreviationUtils');_.each(tree.children,function(item){if(!abbrUtils.isSnippet(item)&&(item.name()||'').toLowerCase()in tags&&item.children.length)trimAttribute(item);process(item);});return tree;});});emmet.define('lorem',function(require,_){var langs={en:{common:['lorem','ipsum','dolor','sit','amet','consectetur','adipisicing','elit'],words:['exercitationem','perferendis','perspiciatis','laborum','eveniet', +'sunt','iure','nam','nobis','eum','cum','officiis','excepturi','odio','consectetur','quasi','aut','quisquam','vel','eligendi','itaque','non','odit','tempore','quaerat','dignissimos','facilis','neque','nihil','expedita','vitae','vero','ipsum','nisi','animi','cumque','pariatur','velit','modi','natus','iusto','eaque','sequi','illo','sed','ex','et','voluptatibus','tempora','veritatis','ratione','assumenda','incidunt','nostrum','placeat','aliquid','fuga','provident','praesentium','rem','necessitatibus','suscipit','adipisci','quidem','possimus','voluptas','debitis','sint','accusantium','unde','sapiente','voluptate','qui','aspernatur','laudantium','soluta','amet','quo','aliquam','saepe','culpa','libero','ipsa','dicta','reiciendis','nesciunt','doloribus','autem','impedit','minima','maiores','repudiandae','ipsam','obcaecati','ullam','enim','totam','delectus','ducimus','quis','voluptates','dolores','molestiae','harum','dolorem','quia','voluptatem','molestias','magni','distinctio','omnis','illum','dolorum','voluptatum','ea', +'quas','quam','corporis','quae','blanditiis','atque','deserunt','laboriosam','earum','consequuntur','hic','cupiditate','quibusdam','accusamus','ut','rerum','error','minus','eius','ab','ad','nemo','fugit','officia','at','in','id','quos','reprehenderit','numquam','iste','fugiat','sit','inventore','beatae','repellendus','magnam','recusandae','quod','explicabo','doloremque','aperiam','consequatur','asperiores','commodi','optio','dolor','labore','temporibus','repellat','veniam','architecto','est','esse','mollitia','nulla','a','similique','eos','alias','dolore','tenetur','deleniti','porro','facere','maxime','corrupti']},ru:{common:['далеко-далеко','за','словесными','горами','в стране','гласных','и согласных','живут','рыбные','тексты'],words:['вдали','от всех','они','буквенных','домах','на берегу','семантика','большого','языкового','океана','маленький','ручеек','даль', +'журчит','по всей','обеспечивает','ее','всеми','необходимыми','правилами','эта','парадигматическая','страна','которой','жаренные','предложения','залетают','прямо','рот','даже','всемогущая','пунктуация','не','имеет','власти','над','рыбными','текстами','ведущими','безорфографичный','образ','жизни','однажды','одна','маленькая','строчка','рыбного','текста','имени','lorem','ipsum','решила','выйти','большой','мир','грамматики','великий','оксмокс','предупреждал','о','злых','запятых','диких','знаках','вопроса','коварных','точках','запятой','но','текст','дал','сбить','себя','толку','он','собрал','семь','своих','заглавных','букв', +'подпоясал','инициал','за','пояс','пустился','дорогу','взобравшись','первую','вершину','курсивных','гор','бросил','последний','взгляд','назад','силуэт','своего','родного','города','буквоград','заголовок','деревни','алфавит','подзаголовок','своего','переулка','грустный','реторический','вопрос','скатился','его','щеке','продолжил','свой','путь','дороге','встретил','рукопись','она','предупредила','моей','все','переписывается','несколько','раз','единственное','что','меня','осталось','это','приставка','возвращайся','ты','лучше','свою','безопасную','страну','послушавшись','рукописи','наш','продолжил','свой','путь','вскоре','ему', +'повстречался','коварный','составитель','рекламных','текстов','напоивший','языком','речью','заманивший','свое','агенство','которое','использовало','снова','снова','своих','проектах','если','переписали','то','живет','там','до','сих','пор']}};var prefs=require('preferences');prefs.define('lorem.defaultLang','en');require('abbreviationParser').addPreprocessor(function(tree,options){var re=/^(?:lorem|lipsum)([a-z]{2})?(\d*)$/i,match;tree.findAll(function(node){if(node._name&&(match=node._name.match(re))){var wordCound=match[2]||30;var lang=match[1]||prefs.get('lorem.defaultLang')||'en';node._name='';node.data('forceNameResolving',node.isRepeating()||node.attributeList().length);node.data('pasteOverwrites',true);node.data('paste',function(i,content){return paragraph(lang,wordCound,!i);});}});});function randint(from,to){return Math.round(Math.random()*(to-from)+from); +}function sample(arr,count){var len=arr.length;var iterations=Math.min(len,count);var result=[];while(result.length3&&len<=6){totalCommas=randint(0,1);}else if(len>6&&len<=12){totalCommas=randint(0,2);}else{totalCommas=randint(1,4);}_.each(_.range(totalCommas),function(ix){if(ix5)words[4]+=',';totalWords+=words.length;result.push(sentence(words,'.'));}while(totalWords","!!!4t":"","!!!4s":"","!!!xt":"","!!!xs":"", +"!!!xxs":"","c":"","cc:ie6":"","cc:ie":"","cc:noie":"\n\t${child}|\n"},"abbreviations":{"!":"html:5","a":"","a:link":"","a:mail":"","abbr":"","acronym":"","base":"","basefont":"","br":"
","frame":"","hr":"
","bdo":"","bdo:r":"","bdo:l":"","col":"","link":"","link:css":"","link:print":"","link:favicon":"","link:touch":"", +"link:rss":"","link:atom":"","meta":"","meta:utf":"","meta:win":"","meta:vp":"","meta:compat":"","style":"\n\ +snippet sub\n\ + ${1}\n\ +snippet summary\n\ + \n\ + ${1}\n\ + \n\ +snippet sup\n\ + ${1}\n\ +snippet table\n\ + \n\ + ${2}\n\ +
\n\ +snippet table.\n\ + \n\ + ${3}\n\ +
\n\ +snippet table#\n\ + \n\ + ${3}\n\ +
\n\ +snippet tbody\n\ + \n\ + ${1}\n\ + \n\ +snippet td\n\ + ${1}\n\ +snippet td.\n\ + ${2}\n\ +snippet td#\n\ + ${2}\n\ +snippet td+\n\ + ${1}\n\ + td+${2}\n\ +snippet textarea\n\ + ${6}\n\ +snippet tfoot\n\ + \n\ + ${1}\n\ + \n\ +snippet th\n\ + ${1}\n\ +snippet th.\n\ + ${2}\n\ +snippet th#\n\ + ${2}\n\ +snippet th+\n\ + ${1}\n\ + th+${2}\n\ +snippet thead\n\ + \n\ + ${1}\n\ + \n\ +snippet time\n\ + \n\ +snippet title\n\ + ${1:`substitute(Filename('', 'Page Title'), '^.', '\\u&', '')`}\n\ +snippet tr\n\ + \n\ + ${1}\n\ + \n\ +snippet tr+\n\ + \n\ + ${1}\n\ + td+${2}\n\ + \n\ +snippet track\n\ + ${5}${6}\n\ +snippet ul\n\ +
    \n\ + ${1}\n\ +
\n\ +snippet ul.\n\ +
    \n\ + ${2}\n\ +
\n\ +snippet ul#\n\ +
    \n\ + ${2}\n\ +
\n\ +snippet ul+\n\ +
    \n\ +
  • ${1}
  • \n\ + li+${2}\n\ +
\n\ +snippet var\n\ + ${1}\n\ +snippet video\n\ + ${8}\n\ +snippet wbr\n\ + ${1}\n\ +"; +exports.scope = "html"; + +}); diff --git a/modules/backend/assets/vendor/ace/snippets/javascript.js b/modules/backend/assets/vendor/ace/snippets/javascript.js new file mode 100644 index 0000000..f3f998a --- /dev/null +++ b/modules/backend/assets/vendor/ace/snippets/javascript.js @@ -0,0 +1,202 @@ +ace.define("ace/snippets/javascript",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# Prototype\n\ +snippet proto\n\ + ${1:class_name}.prototype.${2:method_name} = function(${3:first_argument}) {\n\ + ${4:// body...}\n\ + };\n\ +# Function\n\ +snippet fun\n\ + function ${1?:function_name}(${2:argument}) {\n\ + ${3:// body...}\n\ + }\n\ +# Anonymous Function\n\ +regex /((=)\\s*|(:)\\s*|(\\()|\\b)/f/(\\))?/\n\ +snippet f\n\ + function${M1?: ${1:functionName}}($2) {\n\ + ${0:$TM_SELECTED_TEXT}\n\ + }${M2?;}${M3?,}${M4?)}\n\ +# Immediate function\n\ +trigger \\(?f\\(\n\ +endTrigger \\)?\n\ +snippet f(\n\ + (function(${1}) {\n\ + ${0:${TM_SELECTED_TEXT:/* code */}}\n\ + }(${1}));\n\ +# if\n\ +snippet if\n\ + if (${1:true}) {\n\ + ${0}\n\ + }\n\ +# if ... else\n\ +snippet ife\n\ + if (${1:true}) {\n\ + ${2}\n\ + } else {\n\ + ${0}\n\ + }\n\ +# tertiary conditional\n\ +snippet ter\n\ + ${1:/* condition */} ? ${2:a} : ${3:b}\n\ +# switch\n\ +snippet switch\n\ + switch (${1:expression}) {\n\ + case '${3:case}':\n\ + ${4:// code}\n\ + break;\n\ + ${5}\n\ + default:\n\ + ${2:// code}\n\ + }\n\ +# case\n\ +snippet case\n\ + case '${1:case}':\n\ + ${2:// code}\n\ + break;\n\ + ${3}\n\ +\n\ +# while (...) {...}\n\ +snippet wh\n\ + while (${1:/* condition */}) {\n\ + ${0:/* code */}\n\ + }\n\ +# try\n\ +snippet try\n\ + try {\n\ + ${0:/* code */}\n\ + } catch (e) {}\n\ +# do...while\n\ +snippet do\n\ + do {\n\ + ${2:/* code */}\n\ + } while (${1:/* condition */});\n\ +# Object Method\n\ +snippet :f\n\ +regex /([,{[])|^\\s*/:f/\n\ + ${1:method_name}: function(${2:attribute}) {\n\ + ${0}\n\ + }${3:,}\n\ +# setTimeout function\n\ +snippet setTimeout\n\ +regex /\\b/st|timeout|setTimeo?u?t?/\n\ + setTimeout(function() {${3:$TM_SELECTED_TEXT}}, ${1:10});\n\ +# Get Elements\n\ +snippet gett\n\ + getElementsBy${1:TagName}('${2}')${3}\n\ +# Get Element\n\ +snippet get\n\ + getElementBy${1:Id}('${2}')${3}\n\ +# console.log (Firebug)\n\ +snippet cl\n\ + console.log(${1});\n\ +# return\n\ +snippet ret\n\ + return ${1:result}\n\ +# for (property in object ) { ... }\n\ +snippet fori\n\ + for (var ${1:prop} in ${2:Things}) {\n\ + ${0:$2[$1]}\n\ + }\n\ +# hasOwnProperty\n\ +snippet has\n\ + hasOwnProperty(${1})\n\ +# docstring\n\ +snippet /**\n\ + /**\n\ + * ${1:description}\n\ + *\n\ + */\n\ +snippet @par\n\ +regex /^\\s*\\*\\s*/@(para?m?)?/\n\ + @param {${1:type}} ${2:name} ${3:description}\n\ +snippet @ret\n\ + @return {${1:type}} ${2:description}\n\ +# JSON.parse\n\ +snippet jsonp\n\ + JSON.parse(${1:jstr});\n\ +# JSON.stringify\n\ +snippet jsons\n\ + JSON.stringify(${1:object});\n\ +# self-defining function\n\ +snippet sdf\n\ + var ${1:function_name} = function(${2:argument}) {\n\ + ${3:// initial code ...}\n\ +\n\ + $1 = function($2) {\n\ + ${4:// main code}\n\ + };\n\ + }\n\ +# singleton\n\ +snippet sing\n\ + function ${1:Singleton} (${2:argument}) {\n\ + // the cached instance\n\ + var instance;\n\ +\n\ + // rewrite the constructor\n\ + $1 = function $1($2) {\n\ + return instance;\n\ + };\n\ + \n\ + // carry over the prototype properties\n\ + $1.prototype = this;\n\ +\n\ + // the instance\n\ + instance = new $1();\n\ +\n\ + // reset the constructor pointer\n\ + instance.constructor = $1;\n\ +\n\ + ${3:// code ...}\n\ +\n\ + return instance;\n\ + }\n\ +# class\n\ +snippet class\n\ +regex /^\\s*/clas{0,2}/\n\ + var ${1:class} = function(${20}) {\n\ + $40$0\n\ + };\n\ + \n\ + (function() {\n\ + ${60:this.prop = \"\"}\n\ + }).call(${1:class}.prototype);\n\ + \n\ + exports.${1:class} = ${1:class};\n\ +# \n\ +snippet for-\n\ + for (var ${1:i} = ${2:Things}.length; ${1:i}--; ) {\n\ + ${0:${2:Things}[${1:i}];}\n\ + }\n\ +# for (...) {...}\n\ +snippet for\n\ + for (var ${1:i} = 0; $1 < ${2:Things}.length; $1++) {\n\ + ${3:$2[$1]}$0\n\ + }\n\ +# for (...) {...} (Improved Native For-Loop)\n\ +snippet forr\n\ + for (var ${1:i} = ${2:Things}.length - 1; $1 >= 0; $1--) {\n\ + ${3:$2[$1]}$0\n\ + }\n\ +\n\ +\n\ +#modules\n\ +snippet def\n\ + define(function(require, exports, module) {\n\ + \"use strict\";\n\ + var ${1/.*\\///} = require(\"${1}\");\n\ + \n\ + $TM_SELECTED_TEXT\n\ + });\n\ +snippet req\n\ +guard ^\\s*\n\ + var ${1/.*\\///} = require(\"${1}\");\n\ + $0\n\ +snippet requ\n\ +guard ^\\s*\n\ + var ${1/.*\\/(.)/\\u$1/} = require(\"${1}\").${1/.*\\/(.)/\\u$1/};\n\ + $0\n\ +"; +exports.scope = "javascript"; + +}); diff --git a/modules/backend/assets/vendor/ace/snippets/markdown.js b/modules/backend/assets/vendor/ace/snippets/markdown.js new file mode 100644 index 0000000..d05f16b --- /dev/null +++ b/modules/backend/assets/vendor/ace/snippets/markdown.js @@ -0,0 +1,95 @@ +ace.define("ace/snippets/markdown",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "# Markdown\n\ +\n\ +# Includes octopress (http://octopress.org/) snippets\n\ +\n\ +snippet [\n\ + [${1:text}](http://${2:address} \"${3:title}\")\n\ +snippet [*\n\ + [${1:link}](${2:`@*`} \"${3:title}\")${4}\n\ +\n\ +snippet [:\n\ + [${1:id}]: http://${2:url} \"${3:title}\"\n\ +snippet [:*\n\ + [${1:id}]: ${2:`@*`} \"${3:title}\"\n\ +\n\ +snippet ![\n\ + ![${1:alttext}](${2:/images/image.jpg} \"${3:title}\")\n\ +snippet ![*\n\ + ![${1:alt}](${2:`@*`} \"${3:title}\")${4}\n\ +\n\ +snippet ![:\n\ + ![${1:id}]: ${2:url} \"${3:title}\"\n\ +snippet ![:*\n\ + ![${1:id}]: ${2:`@*`} \"${3:title}\"\n\ +\n\ +snippet ===\n\ +regex /^/=+/=*//\n\ + ${PREV_LINE/./=/g}\n\ + \n\ + ${0}\n\ +snippet ---\n\ +regex /^/-+/-*//\n\ + ${PREV_LINE/./-/g}\n\ + \n\ + ${0}\n\ +snippet blockquote\n\ + {% blockquote %}\n\ + ${1:quote}\n\ + {% endblockquote %}\n\ +\n\ +snippet blockquote-author\n\ + {% blockquote ${1:author}, ${2:title} %}\n\ + ${3:quote}\n\ + {% endblockquote %}\n\ +\n\ +snippet blockquote-link\n\ + {% blockquote ${1:author} ${2:URL} ${3:link_text} %}\n\ + ${4:quote}\n\ + {% endblockquote %}\n\ +\n\ +snippet bt-codeblock-short\n\ + ```\n\ + ${1:code_snippet}\n\ + ```\n\ +\n\ +snippet bt-codeblock-full\n\ + ``` ${1:language} ${2:title} ${3:URL} ${4:link_text}\n\ + ${5:code_snippet}\n\ + ```\n\ +\n\ +snippet codeblock-short\n\ + {% codeblock %}\n\ + ${1:code_snippet}\n\ + {% endcodeblock %}\n\ +\n\ +snippet codeblock-full\n\ + {% codeblock ${1:title} lang:${2:language} ${3:URL} ${4:link_text} %}\n\ + ${5:code_snippet}\n\ + {% endcodeblock %}\n\ +\n\ +snippet gist-full\n\ + {% gist ${1:gist_id} ${2:filename} %}\n\ +\n\ +snippet gist-short\n\ + {% gist ${1:gist_id} %}\n\ +\n\ +snippet img\n\ + {% img ${1:class} ${2:URL} ${3:width} ${4:height} ${5:title_text} ${6:alt_text} %}\n\ +\n\ +snippet youtube\n\ + {% youtube ${1:video_id} %}\n\ +\n\ +# The quote should appear only once in the text. It is inherently part of it.\n\ +# See http://octopress.org/docs/plugins/pullquote/ for more info.\n\ +\n\ +snippet pullquote\n\ + {% pullquote %}\n\ + ${1:text} {\" ${2:quote} \"} ${3:text}\n\ + {% endpullquote %}\n\ +"; +exports.scope = "markdown"; + +}); diff --git a/modules/backend/assets/vendor/ace/snippets/php-inline.js b/modules/backend/assets/vendor/ace/snippets/php-inline.js new file mode 100644 index 0000000..a99ab6e --- /dev/null +++ b/modules/backend/assets/vendor/ace/snippets/php-inline.js @@ -0,0 +1,384 @@ +ace.define("ace/snippets/php",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet \n\ +# this one is for php5.4\n\ +snippet \n\ +snippet ns\n\ + namespace ${1:Foo\\Bar\\Baz};\n\ + ${2}\n\ +snippet use\n\ + use ${1:Foo\\Bar\\Baz};\n\ + ${2}\n\ +snippet c\n\ + ${1:abstract }class ${2:$FILENAME}\n\ + {\n\ + ${3}\n\ + }\n\ +snippet i\n\ + interface ${1:$FILENAME}\n\ + {\n\ + ${2}\n\ + }\n\ +snippet t.\n\ + $this->${1}\n\ +snippet f\n\ + function ${1:foo}(${2:array }${3:$bar})\n\ + {\n\ + ${4}\n\ + }\n\ +# method\n\ +snippet m\n\ + ${1:abstract }${2:protected}${3: static} function ${4:foo}(${5:array }${6:$bar})\n\ + {\n\ + ${7}\n\ + }\n\ +# setter method\n\ +snippet sm \n\ + /**\n\ + * Sets the value of ${1:foo}\n\ + *\n\ + * @param ${2:$1} $$1 ${3:description}\n\ + *\n\ + * @return ${4:$FILENAME}\n\ + */\n\ + ${5:public} function set${6:$2}(${7:$2 }$$1)\n\ + {\n\ + $this->${8:$1} = $$1;\n\ + return $this;\n\ + }${9}\n\ +# getter method\n\ +snippet gm\n\ + /**\n\ + * Gets the value of ${1:foo}\n\ + *\n\ + * @return ${2:$1}\n\ + */\n\ + ${3:public} function get${4:$2}()\n\ + {\n\ + return $this->${5:$1};\n\ + }${6}\n\ +#setter\n\ +snippet $s\n\ + ${1:$foo}->set${2:Bar}(${3});\n\ +#getter\n\ +snippet $g\n\ + ${1:$foo}->get${2:Bar}();\n\ +\n\ +# Tertiary conditional\n\ +snippet =?:\n\ + $${1:foo} = ${2:true} ? ${3:a} : ${4};\n\ +snippet ?:\n\ + ${1:true} ? ${2:a} : ${3}\n\ +\n\ +snippet C\n\ + $_COOKIE['${1:variable}']${2}\n\ +snippet E\n\ + $_ENV['${1:variable}']${2}\n\ +snippet F\n\ + $_FILES['${1:variable}']${2}\n\ +snippet G\n\ + $_GET['${1:variable}']${2}\n\ +snippet P\n\ + $_POST['${1:variable}']${2}\n\ +snippet R\n\ + $_REQUEST['${1:variable}']${2}\n\ +snippet S\n\ + $_SERVER['${1:variable}']${2}\n\ +snippet SS\n\ + $_SESSION['${1:variable}']${2}\n\ + \n\ +# the following are old ones\n\ +snippet inc\n\ + include '${1:file}';${2}\n\ +snippet inc1\n\ + include_once '${1:file}';${2}\n\ +snippet req\n\ + require '${1:file}';${2}\n\ +snippet req1\n\ + require_once '${1:file}';${2}\n\ +# Start Docblock\n\ +snippet /*\n\ + /**\n\ + * ${1}\n\ + */\n\ +# Class - post doc\n\ +snippet doc_cp\n\ + /**\n\ + * ${1:undocumented class}\n\ + *\n\ + * @package ${2:default}\n\ + * @subpackage ${3:default}\n\ + * @author ${4:`g:snips_author`}\n\ + */${5}\n\ +# Class Variable - post doc\n\ +snippet doc_vp\n\ + /**\n\ + * ${1:undocumented class variable}\n\ + *\n\ + * @var ${2:string}\n\ + */${3}\n\ +# Class Variable\n\ +snippet doc_v\n\ + /**\n\ + * ${3:undocumented class variable}\n\ + *\n\ + * @var ${4:string}\n\ + */\n\ + ${1:var} $${2};${5}\n\ +# Class\n\ +snippet doc_c\n\ + /**\n\ + * ${3:undocumented class}\n\ + *\n\ + * @package ${4:default}\n\ + * @subpackage ${5:default}\n\ + * @author ${6:`g:snips_author`}\n\ + */\n\ + ${1:}class ${2:}\n\ + {\n\ + ${7}\n\ + } // END $1class $2\n\ +# Constant Definition - post doc\n\ +snippet doc_dp\n\ + /**\n\ + * ${1:undocumented constant}\n\ + */${2}\n\ +# Constant Definition\n\ +snippet doc_d\n\ + /**\n\ + * ${3:undocumented constant}\n\ + */\n\ + define(${1}, ${2});${4}\n\ +# Function - post doc\n\ +snippet doc_fp\n\ + /**\n\ + * ${1:undocumented function}\n\ + *\n\ + * @return ${2:void}\n\ + * @author ${3:`g:snips_author`}\n\ + */${4}\n\ +# Function signature\n\ +snippet doc_s\n\ + /**\n\ + * ${4:undocumented function}\n\ + *\n\ + * @return ${5:void}\n\ + * @author ${6:`g:snips_author`}\n\ + */\n\ + ${1}function ${2}(${3});${7}\n\ +# Function\n\ +snippet doc_f\n\ + /**\n\ + * ${4:undocumented function}\n\ + *\n\ + * @return ${5:void}\n\ + * @author ${6:`g:snips_author`}\n\ + */\n\ + ${1}function ${2}(${3})\n\ + {${7}\n\ + }\n\ +# Header\n\ +snippet doc_h\n\ + /**\n\ + * ${1}\n\ + *\n\ + * @author ${2:`g:snips_author`}\n\ + * @version ${3:$Id$}\n\ + * @copyright ${4:$2}, `strftime('%d %B, %Y')`\n\ + * @package ${5:default}\n\ + */\n\ + \n\ +# Interface\n\ +snippet interface\n\ + /**\n\ + * ${2:undocumented class}\n\ + *\n\ + * @package ${3:default}\n\ + * @author ${4:`g:snips_author`}\n\ + */\n\ + interface ${1:$FILENAME}\n\ + {\n\ + ${5}\n\ + }\n\ +# class ...\n\ +snippet class\n\ + /**\n\ + * ${1}\n\ + */\n\ + class ${2:$FILENAME}\n\ + {\n\ + ${3}\n\ + /**\n\ + * ${4}\n\ + */\n\ + ${5:public} function ${6:__construct}(${7:argument})\n\ + {\n\ + ${8:// code...}\n\ + }\n\ + }\n\ +# define(...)\n\ +snippet def\n\ + define('${1}'${2});${3}\n\ +# defined(...)\n\ +snippet def?\n\ + ${1}defined('${2}')${3}\n\ +snippet wh\n\ + while (${1:/* condition */}) {\n\ + ${2:// code...}\n\ + }\n\ +# do ... while\n\ +snippet do\n\ + do {\n\ + ${2:// code... }\n\ + } while (${1:/* condition */});\n\ +snippet if\n\ + if (${1:/* condition */}) {\n\ + ${2:// code...}\n\ + }\n\ +snippet ifil\n\ + \n\ + ${2:}\n\ + \n\ +snippet ife\n\ + if (${1:/* condition */}) {\n\ + ${2:// code...}\n\ + } else {\n\ + ${3:// code...}\n\ + }\n\ + ${4}\n\ +snippet ifeil\n\ + \n\ + ${2:}\n\ + \n\ + ${3:}\n\ + \n\ + ${4}\n\ +snippet else\n\ + else {\n\ + ${1:// code...}\n\ + }\n\ +snippet elseif\n\ + elseif (${1:/* condition */}) {\n\ + ${2:// code...}\n\ + }\n\ +snippet switch\n\ + switch ($${1:variable}) {\n\ + case '${2:value}':\n\ + ${3:// code...}\n\ + break;\n\ + ${5}\n\ + default:\n\ + ${4:// code...}\n\ + break;\n\ + }\n\ +snippet case\n\ + case '${1:value}':\n\ + ${2:// code...}\n\ + break;${3}\n\ +snippet for\n\ + for ($${2:i} = 0; $$2 < ${1:count}; $$2${3:++}) {\n\ + ${4: // code...}\n\ + }\n\ +snippet foreach\n\ + foreach ($${1:variable} as $${2:value}) {\n\ + ${3:// code...}\n\ + }\n\ +snippet foreachil\n\ + \n\ + ${3:}\n\ + \n\ +snippet foreachk\n\ + foreach ($${1:variable} as $${2:key} => $${3:value}) {\n\ + ${4:// code...}\n\ + }\n\ +snippet foreachkil\n\ + $${3:value}): ?>\n\ + ${4:}\n\ + \n\ +# $... = array (...)\n\ +snippet array\n\ + $${1:arrayName} = array('${2}' => ${3});${4}\n\ +snippet try\n\ + try {\n\ + ${2}\n\ + } catch (${1:Exception} $e) {\n\ + }\n\ +# lambda with closure\n\ +snippet lambda\n\ + ${1:static }function (${2:args}) use (${3:&$x, $y /*put vars in scope (closure) */}) {\n\ + ${4}\n\ + };\n\ +# pre_dump();\n\ +snippet pd\n\ + echo '
'; var_dump(${1}); echo '
';\n\ +# pre_dump(); die();\n\ +snippet pdd\n\ + echo '
'; var_dump(${1}); echo '
'; die(${2:});\n\ +snippet vd\n\ + var_dump(${1});\n\ +snippet vdd\n\ + var_dump(${1}); die(${2:});\n\ +snippet http_redirect\n\ + header (\"HTTP/1.1 301 Moved Permanently\"); \n\ + header (\"Location: \".URL); \n\ + exit();\n\ +# Getters & Setters\n\ +snippet gs\n\ + /**\n\ + * Gets the value of ${1:foo}\n\ + *\n\ + * @return ${2:$1}\n\ + */\n\ + public function get${3:$2}()\n\ + {\n\ + return $this->${4:$1};\n\ + }\n\ +\n\ + /**\n\ + * Sets the value of $1\n\ + *\n\ + * @param $2 $$1 ${5:description}\n\ + *\n\ + * @return ${6:$FILENAME}\n\ + */\n\ + public function set$3(${7:$2 }$$1)\n\ + {\n\ + $this->$4 = $$1;\n\ + return $this;\n\ + }${8}\n\ +# anotation, get, and set, useful for doctrine\n\ +snippet ags\n\ + /**\n\ + * ${1:description}\n\ + * \n\ + * @${7}\n\ + */\n\ + ${2:protected} $${3:foo};\n\ +\n\ + public function get${4:$3}()\n\ + {\n\ + return $this->$3;\n\ + }\n\ +\n\ + public function set$4(${5:$4 }$${6:$3})\n\ + {\n\ + $this->$3 = $$6;\n\ + return $this;\n\ + }\n\ +snippet rett\n\ + return true;\n\ +snippet retf\n\ + return false;\n\ +"; +exports.scope = "php"; + +}); diff --git a/modules/backend/assets/vendor/ace/snippets/php.js b/modules/backend/assets/vendor/ace/snippets/php.js new file mode 100644 index 0000000..a99ab6e --- /dev/null +++ b/modules/backend/assets/vendor/ace/snippets/php.js @@ -0,0 +1,384 @@ +ace.define("ace/snippets/php",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText = "snippet \n\ +# this one is for php5.4\n\ +snippet \n\ +snippet ns\n\ + namespace ${1:Foo\\Bar\\Baz};\n\ + ${2}\n\ +snippet use\n\ + use ${1:Foo\\Bar\\Baz};\n\ + ${2}\n\ +snippet c\n\ + ${1:abstract }class ${2:$FILENAME}\n\ + {\n\ + ${3}\n\ + }\n\ +snippet i\n\ + interface ${1:$FILENAME}\n\ + {\n\ + ${2}\n\ + }\n\ +snippet t.\n\ + $this->${1}\n\ +snippet f\n\ + function ${1:foo}(${2:array }${3:$bar})\n\ + {\n\ + ${4}\n\ + }\n\ +# method\n\ +snippet m\n\ + ${1:abstract }${2:protected}${3: static} function ${4:foo}(${5:array }${6:$bar})\n\ + {\n\ + ${7}\n\ + }\n\ +# setter method\n\ +snippet sm \n\ + /**\n\ + * Sets the value of ${1:foo}\n\ + *\n\ + * @param ${2:$1} $$1 ${3:description}\n\ + *\n\ + * @return ${4:$FILENAME}\n\ + */\n\ + ${5:public} function set${6:$2}(${7:$2 }$$1)\n\ + {\n\ + $this->${8:$1} = $$1;\n\ + return $this;\n\ + }${9}\n\ +# getter method\n\ +snippet gm\n\ + /**\n\ + * Gets the value of ${1:foo}\n\ + *\n\ + * @return ${2:$1}\n\ + */\n\ + ${3:public} function get${4:$2}()\n\ + {\n\ + return $this->${5:$1};\n\ + }${6}\n\ +#setter\n\ +snippet $s\n\ + ${1:$foo}->set${2:Bar}(${3});\n\ +#getter\n\ +snippet $g\n\ + ${1:$foo}->get${2:Bar}();\n\ +\n\ +# Tertiary conditional\n\ +snippet =?:\n\ + $${1:foo} = ${2:true} ? ${3:a} : ${4};\n\ +snippet ?:\n\ + ${1:true} ? ${2:a} : ${3}\n\ +\n\ +snippet C\n\ + $_COOKIE['${1:variable}']${2}\n\ +snippet E\n\ + $_ENV['${1:variable}']${2}\n\ +snippet F\n\ + $_FILES['${1:variable}']${2}\n\ +snippet G\n\ + $_GET['${1:variable}']${2}\n\ +snippet P\n\ + $_POST['${1:variable}']${2}\n\ +snippet R\n\ + $_REQUEST['${1:variable}']${2}\n\ +snippet S\n\ + $_SERVER['${1:variable}']${2}\n\ +snippet SS\n\ + $_SESSION['${1:variable}']${2}\n\ + \n\ +# the following are old ones\n\ +snippet inc\n\ + include '${1:file}';${2}\n\ +snippet inc1\n\ + include_once '${1:file}';${2}\n\ +snippet req\n\ + require '${1:file}';${2}\n\ +snippet req1\n\ + require_once '${1:file}';${2}\n\ +# Start Docblock\n\ +snippet /*\n\ + /**\n\ + * ${1}\n\ + */\n\ +# Class - post doc\n\ +snippet doc_cp\n\ + /**\n\ + * ${1:undocumented class}\n\ + *\n\ + * @package ${2:default}\n\ + * @subpackage ${3:default}\n\ + * @author ${4:`g:snips_author`}\n\ + */${5}\n\ +# Class Variable - post doc\n\ +snippet doc_vp\n\ + /**\n\ + * ${1:undocumented class variable}\n\ + *\n\ + * @var ${2:string}\n\ + */${3}\n\ +# Class Variable\n\ +snippet doc_v\n\ + /**\n\ + * ${3:undocumented class variable}\n\ + *\n\ + * @var ${4:string}\n\ + */\n\ + ${1:var} $${2};${5}\n\ +# Class\n\ +snippet doc_c\n\ + /**\n\ + * ${3:undocumented class}\n\ + *\n\ + * @package ${4:default}\n\ + * @subpackage ${5:default}\n\ + * @author ${6:`g:snips_author`}\n\ + */\n\ + ${1:}class ${2:}\n\ + {\n\ + ${7}\n\ + } // END $1class $2\n\ +# Constant Definition - post doc\n\ +snippet doc_dp\n\ + /**\n\ + * ${1:undocumented constant}\n\ + */${2}\n\ +# Constant Definition\n\ +snippet doc_d\n\ + /**\n\ + * ${3:undocumented constant}\n\ + */\n\ + define(${1}, ${2});${4}\n\ +# Function - post doc\n\ +snippet doc_fp\n\ + /**\n\ + * ${1:undocumented function}\n\ + *\n\ + * @return ${2:void}\n\ + * @author ${3:`g:snips_author`}\n\ + */${4}\n\ +# Function signature\n\ +snippet doc_s\n\ + /**\n\ + * ${4:undocumented function}\n\ + *\n\ + * @return ${5:void}\n\ + * @author ${6:`g:snips_author`}\n\ + */\n\ + ${1}function ${2}(${3});${7}\n\ +# Function\n\ +snippet doc_f\n\ + /**\n\ + * ${4:undocumented function}\n\ + *\n\ + * @return ${5:void}\n\ + * @author ${6:`g:snips_author`}\n\ + */\n\ + ${1}function ${2}(${3})\n\ + {${7}\n\ + }\n\ +# Header\n\ +snippet doc_h\n\ + /**\n\ + * ${1}\n\ + *\n\ + * @author ${2:`g:snips_author`}\n\ + * @version ${3:$Id$}\n\ + * @copyright ${4:$2}, `strftime('%d %B, %Y')`\n\ + * @package ${5:default}\n\ + */\n\ + \n\ +# Interface\n\ +snippet interface\n\ + /**\n\ + * ${2:undocumented class}\n\ + *\n\ + * @package ${3:default}\n\ + * @author ${4:`g:snips_author`}\n\ + */\n\ + interface ${1:$FILENAME}\n\ + {\n\ + ${5}\n\ + }\n\ +# class ...\n\ +snippet class\n\ + /**\n\ + * ${1}\n\ + */\n\ + class ${2:$FILENAME}\n\ + {\n\ + ${3}\n\ + /**\n\ + * ${4}\n\ + */\n\ + ${5:public} function ${6:__construct}(${7:argument})\n\ + {\n\ + ${8:// code...}\n\ + }\n\ + }\n\ +# define(...)\n\ +snippet def\n\ + define('${1}'${2});${3}\n\ +# defined(...)\n\ +snippet def?\n\ + ${1}defined('${2}')${3}\n\ +snippet wh\n\ + while (${1:/* condition */}) {\n\ + ${2:// code...}\n\ + }\n\ +# do ... while\n\ +snippet do\n\ + do {\n\ + ${2:// code... }\n\ + } while (${1:/* condition */});\n\ +snippet if\n\ + if (${1:/* condition */}) {\n\ + ${2:// code...}\n\ + }\n\ +snippet ifil\n\ + \n\ + ${2:}\n\ + \n\ +snippet ife\n\ + if (${1:/* condition */}) {\n\ + ${2:// code...}\n\ + } else {\n\ + ${3:// code...}\n\ + }\n\ + ${4}\n\ +snippet ifeil\n\ + \n\ + ${2:}\n\ + \n\ + ${3:}\n\ + \n\ + ${4}\n\ +snippet else\n\ + else {\n\ + ${1:// code...}\n\ + }\n\ +snippet elseif\n\ + elseif (${1:/* condition */}) {\n\ + ${2:// code...}\n\ + }\n\ +snippet switch\n\ + switch ($${1:variable}) {\n\ + case '${2:value}':\n\ + ${3:// code...}\n\ + break;\n\ + ${5}\n\ + default:\n\ + ${4:// code...}\n\ + break;\n\ + }\n\ +snippet case\n\ + case '${1:value}':\n\ + ${2:// code...}\n\ + break;${3}\n\ +snippet for\n\ + for ($${2:i} = 0; $$2 < ${1:count}; $$2${3:++}) {\n\ + ${4: // code...}\n\ + }\n\ +snippet foreach\n\ + foreach ($${1:variable} as $${2:value}) {\n\ + ${3:// code...}\n\ + }\n\ +snippet foreachil\n\ + \n\ + ${3:}\n\ + \n\ +snippet foreachk\n\ + foreach ($${1:variable} as $${2:key} => $${3:value}) {\n\ + ${4:// code...}\n\ + }\n\ +snippet foreachkil\n\ + $${3:value}): ?>\n\ + ${4:}\n\ + \n\ +# $... = array (...)\n\ +snippet array\n\ + $${1:arrayName} = array('${2}' => ${3});${4}\n\ +snippet try\n\ + try {\n\ + ${2}\n\ + } catch (${1:Exception} $e) {\n\ + }\n\ +# lambda with closure\n\ +snippet lambda\n\ + ${1:static }function (${2:args}) use (${3:&$x, $y /*put vars in scope (closure) */}) {\n\ + ${4}\n\ + };\n\ +# pre_dump();\n\ +snippet pd\n\ + echo '
'; var_dump(${1}); echo '
';\n\ +# pre_dump(); die();\n\ +snippet pdd\n\ + echo '
'; var_dump(${1}); echo '
'; die(${2:});\n\ +snippet vd\n\ + var_dump(${1});\n\ +snippet vdd\n\ + var_dump(${1}); die(${2:});\n\ +snippet http_redirect\n\ + header (\"HTTP/1.1 301 Moved Permanently\"); \n\ + header (\"Location: \".URL); \n\ + exit();\n\ +# Getters & Setters\n\ +snippet gs\n\ + /**\n\ + * Gets the value of ${1:foo}\n\ + *\n\ + * @return ${2:$1}\n\ + */\n\ + public function get${3:$2}()\n\ + {\n\ + return $this->${4:$1};\n\ + }\n\ +\n\ + /**\n\ + * Sets the value of $1\n\ + *\n\ + * @param $2 $$1 ${5:description}\n\ + *\n\ + * @return ${6:$FILENAME}\n\ + */\n\ + public function set$3(${7:$2 }$$1)\n\ + {\n\ + $this->$4 = $$1;\n\ + return $this;\n\ + }${8}\n\ +# anotation, get, and set, useful for doctrine\n\ +snippet ags\n\ + /**\n\ + * ${1:description}\n\ + * \n\ + * @${7}\n\ + */\n\ + ${2:protected} $${3:foo};\n\ +\n\ + public function get${4:$3}()\n\ + {\n\ + return $this->$3;\n\ + }\n\ +\n\ + public function set$4(${5:$4 }$${6:$3})\n\ + {\n\ + $this->$3 = $$6;\n\ + return $this;\n\ + }\n\ +snippet rett\n\ + return true;\n\ +snippet retf\n\ + return false;\n\ +"; +exports.scope = "php"; + +}); diff --git a/modules/backend/assets/vendor/ace/snippets/plain_text.js b/modules/backend/assets/vendor/ace/snippets/plain_text.js new file mode 100644 index 0000000..24223a6 --- /dev/null +++ b/modules/backend/assets/vendor/ace/snippets/plain_text.js @@ -0,0 +1,7 @@ +ace.define("ace/snippets/plain_text",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "plain_text"; + +}); diff --git a/modules/backend/assets/vendor/ace/snippets/sass.js b/modules/backend/assets/vendor/ace/snippets/sass.js new file mode 100644 index 0000000..b9adc9d --- /dev/null +++ b/modules/backend/assets/vendor/ace/snippets/sass.js @@ -0,0 +1,7 @@ +ace.define("ace/snippets/sass",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "sass"; + +}); diff --git a/modules/backend/assets/vendor/ace/snippets/scss.js b/modules/backend/assets/vendor/ace/snippets/scss.js new file mode 100644 index 0000000..fbd98f7 --- /dev/null +++ b/modules/backend/assets/vendor/ace/snippets/scss.js @@ -0,0 +1,7 @@ +ace.define("ace/snippets/scss",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "scss"; + +}); diff --git a/modules/backend/assets/vendor/ace/snippets/text.js b/modules/backend/assets/vendor/ace/snippets/text.js new file mode 100644 index 0000000..57b897b --- /dev/null +++ b/modules/backend/assets/vendor/ace/snippets/text.js @@ -0,0 +1,7 @@ +ace.define("ace/snippets/text",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "text"; + +}); diff --git a/modules/backend/assets/vendor/ace/snippets/twig.js b/modules/backend/assets/vendor/ace/snippets/twig.js new file mode 100644 index 0000000..ccc6073 --- /dev/null +++ b/modules/backend/assets/vendor/ace/snippets/twig.js @@ -0,0 +1,7 @@ +ace.define("ace/snippets/twig",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "twig"; + +}); diff --git a/modules/backend/assets/vendor/ace/snippets/yaml.js b/modules/backend/assets/vendor/ace/snippets/yaml.js new file mode 100644 index 0000000..1adceab --- /dev/null +++ b/modules/backend/assets/vendor/ace/snippets/yaml.js @@ -0,0 +1,7 @@ +ace.define("ace/snippets/yaml",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.snippetText =undefined; +exports.scope = "yaml"; + +}); diff --git a/modules/backend/assets/vendor/ace/theme-ambiance.js b/modules/backend/assets/vendor/ace/theme-ambiance.js new file mode 100755 index 0000000..1e53ecd --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-ambiance.js @@ -0,0 +1,182 @@ +ace.define("ace/theme/ambiance",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-ambiance"; +exports.cssText = ".ace-ambiance .ace_gutter {\ +background-color: #3d3d3d;\ +background-image: -moz-linear-gradient(left, #3D3D3D, #333);\ +background-image: -ms-linear-gradient(left, #3D3D3D, #333);\ +background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#3D3D3D), to(#333));\ +background-image: -webkit-linear-gradient(left, #3D3D3D, #333);\ +background-image: -o-linear-gradient(left, #3D3D3D, #333);\ +background-image: linear-gradient(left, #3D3D3D, #333);\ +background-repeat: repeat-x;\ +border-right: 1px solid #4d4d4d;\ +text-shadow: 0px 1px 1px #4d4d4d;\ +color: #222;\ +}\ +.ace-ambiance .ace_gutter-layer {\ +background: repeat left top;\ +}\ +.ace-ambiance .ace_gutter-active-line {\ +background-color: #3F3F3F;\ +}\ +.ace-ambiance .ace_fold-widget {\ +text-align: center;\ +}\ +.ace-ambiance .ace_fold-widget:hover {\ +color: #777;\ +}\ +.ace-ambiance .ace_fold-widget.ace_start,\ +.ace-ambiance .ace_fold-widget.ace_end,\ +.ace-ambiance .ace_fold-widget.ace_closed{\ +background: none;\ +border: none;\ +box-shadow: none;\ +}\ +.ace-ambiance .ace_fold-widget.ace_start:after {\ +content: '▾'\ +}\ +.ace-ambiance .ace_fold-widget.ace_end:after {\ +content: '▴'\ +}\ +.ace-ambiance .ace_fold-widget.ace_closed:after {\ +content: '‣'\ +}\ +.ace-ambiance .ace_print-margin {\ +border-left: 1px dotted #2D2D2D;\ +right: 0;\ +background: #262626;\ +}\ +.ace-ambiance .ace_scroller {\ +-webkit-box-shadow: inset 0 0 10px black;\ +-moz-box-shadow: inset 0 0 10px black;\ +-o-box-shadow: inset 0 0 10px black;\ +box-shadow: inset 0 0 10px black;\ +}\ +.ace-ambiance {\ +color: #E6E1DC;\ +background-color: #202020;\ +}\ +.ace-ambiance .ace_cursor {\ +border-left: 1px solid #7991E8;\ +}\ +.ace-ambiance .ace_overwrite-cursors .ace_cursor {\ +border: 1px solid #FFE300;\ +background: #766B13;\ +}\ +.ace-ambiance.normal-mode .ace_cursor-layer {\ +z-index: 0;\ +}\ +.ace-ambiance .ace_marker-layer .ace_selection {\ +background: rgba(221, 240, 255, 0.20);\ +}\ +.ace-ambiance .ace_marker-layer .ace_selected-word {\ +border-radius: 4px;\ +border: 8px solid #3f475d;\ +box-shadow: 0 0 4px black;\ +}\ +.ace-ambiance .ace_marker-layer .ace_step {\ +background: rgb(198, 219, 174);\ +}\ +.ace-ambiance .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgba(255, 255, 255, 0.25);\ +}\ +.ace-ambiance .ace_marker-layer .ace_active-line {\ +background: rgba(255, 255, 255, 0.031);\ +}\ +.ace-ambiance .ace_invisible {\ +color: #333;\ +}\ +.ace-ambiance .ace_paren {\ +color: #24C2C7;\ +}\ +.ace-ambiance .ace_keyword {\ +color: #cda869;\ +}\ +.ace-ambiance .ace_keyword.ace_operator {\ +color: #fa8d6a;\ +}\ +.ace-ambiance .ace_punctuation.ace_operator {\ +color: #fa8d6a;\ +}\ +.ace-ambiance .ace_identifier {\ +}\ +.ace-ambiance .ace-statement {\ +color: #cda869;\ +}\ +.ace-ambiance .ace_constant {\ +color: #CF7EA9;\ +}\ +.ace-ambiance .ace_constant.ace_language {\ +color: #CF7EA9;\ +}\ +.ace-ambiance .ace_constant.ace_library {\ +}\ +.ace-ambiance .ace_constant.ace_numeric {\ +color: #78CF8A;\ +}\ +.ace-ambiance .ace_invalid {\ +text-decoration: underline;\ +}\ +.ace-ambiance .ace_invalid.ace_illegal {\ +color:#F8F8F8;\ +background-color: rgba(86, 45, 86, 0.75);\ +}\ +.ace-ambiance .ace_invalid,\ +.ace-ambiance .ace_deprecated {\ +text-decoration: underline;\ +font-style: italic;\ +color: #D2A8A1;\ +}\ +.ace-ambiance .ace_support {\ +color: #9B859D;\ +}\ +.ace-ambiance .ace_support.ace_function {\ +color: #DAD085;\ +}\ +.ace-ambiance .ace_function.ace_buildin {\ +color: #9b859d;\ +}\ +.ace-ambiance .ace_string {\ +color: #8f9d6a;\ +}\ +.ace-ambiance .ace_string.ace_regexp {\ +color: #DAD085;\ +}\ +.ace-ambiance .ace_comment {\ +font-style: italic;\ +color: #555;\ +}\ +.ace-ambiance .ace_comment.ace_doc {\ +}\ +.ace-ambiance .ace_comment.ace_doc.ace_tag {\ +color: #666;\ +font-style: normal;\ +}\ +.ace-ambiance .ace_definition,\ +.ace-ambiance .ace_type {\ +color: #aac6e3;\ +}\ +.ace-ambiance .ace_variable {\ +color: #9999cc;\ +}\ +.ace-ambiance .ace_variable.ace_language {\ +color: #9b859d;\ +}\ +.ace-ambiance .ace_xml-pe {\ +color: #494949;\ +}\ +.ace-ambiance .ace_gutter-layer,\ +.ace-ambiance .ace_text-layer {\ +background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAQAAAAHUWYVAABFFUlEQVQYGbzBCeDVU/74/6fj9HIcx/FRHx9JCFmzMyGRURhLZIkUsoeRfUjS2FNDtr6WkMhO9sm+S8maJfu+Jcsg+/o/c+Z4z/t97/vezy3z+z8ekGlnYICG/o7gdk+wmSHZ1z4pJItqapjoKXWahm8NmV6eOTbWUOp6/6a/XIg6GQqmenJ2lDHyvCFZ2cBDbmtHA043VFhHwXxClWmeYAdLhV00Bd85go8VmaFCkbVkzlQENzfBDZ5gtN7HwF0KDrTwJ0dypSOzpaKCMwQHKTIreYIxlmhXTzTWkVm+LTynZhiSBT3RZQ7aGfjGEd3qyXQ1FDymqbKxpspERQN2MiRjNZlFFQXfCNFm9nM1zpAsoYjmtRTc5ajwuaXc5xrWskT97RaKzAGe5ARHhVUsDbjKklziiX5WROcJwSNCNI+9w1Jwv4Zb2r7lCMZ4oq5C0EdTx+2GzNuKpJ+iFf38JEWkHJn9DNF7mmBDITrWEg0VWL3pHU20tSZnuqWu+R3BtYa8XxV1HO7GyD32UkOpL/yDloINFTmvtId+nmAjxRw40VMwVKiwrKLE4bK5UOVntYwhOcSSXKrJHKPJedocpGjVz/ZMIbnYUPB10/eKCrs5apqpgVmWzBYWpmtKHecJPjaUuEgRDDaU0oZghCJ6zNMQ5ZhDYx05r5v2muQdM0EILtXUsaKiQX9WMEUotagQzFbUNN6NUPC2nm5pxEWGCjMc3GdJHjSU2kORLK/JGSrkfGEIjncU/CYUnOipoYemwj8tST9NsJmB7TUVXtbUtXATJVZXBMvYeTXJfobgJUPmGMP/yFaWonaa6BcFO3nqcIqCozSZoZoSr1g4zJOzuyGnxTEX3lUEJ7WcZgme8ddaWvWJo2AJR9DZU3CUIbhCSG6ybSwN6qtJVnCU2svDTP2ZInOw2cBTrqtQahtNZn9NcJ4l2NaSmSkkP1noZWnVwkLmdUPOwLZEwy2Z3S3R+4rIG9hcbpPXHFVWcQdZkn2FOta3cKWQnNRC5g1LsJah4GCzSVsKnCOY5OAFRTBekyyryeyilhFKva75r4Mc0aWanGEaThcy31s439KKxTzJYY5WTHPU1FtIHjQU3Oip4xlNzj/lBw23dYZVliQa7WAXf4shetcQfatI+jWRDBPmyNeW6A1P5kdDgyYJlba0BIM8BZu1JfrFwItyjcAMR3K0BWOIrtMEXyhyrlVEx3ui5dUBjmB/Q3CXW85R4mBD0s7B+4q5tKUjOlb9qqmhi5AZ6GFIC5HXtOobdYGlVdMVbNJ8toNTFcHxnoL+muBagcctjWnbNMuR00uI7nQESwg5q2qqrKWIfrNUmeQocY6HuyxJV02wj36w00yhpmUFenv4p6fUkZYqLyuinx2RGOjhCXYyJF84oiU00YMOOhhquNdfbOB7gU88pY4xJO8LVdp6/q2voeB4R04vIdhSE40xZObx1HGGJ/ja0LBthFInKaLPPFzuCaYaoj8JjPME8yoyxo6zlBqkiUZYgq00OYMswbWO5NGmq+xhipxHLRW29ARjNKXO0wRnear8XSg4XFPLKEPUS1GqvyLwiuBUoa7zpZ0l5xxFwWmWZC1H5h5FwU8eQ7K+g8UcVY6TMQreVQT/8uQ8Z+ALIXnSEa2pYZQneE9RZbSBNYXfWYJzW/h/4j4Dp1tYVcFIC5019Vyi4ThPqSFCzjGWaHQTBU8q6vrVwgxP9Lkm840imWKpcLCjYTtrKuwvsKSnrvHCXGkSMk9p6lhckfRpIeis+N2PiszT+mFLspyGleUhDwcLrZqmyeylxwjBcKHEapqkmyangyLZRVOijwOtCY5SsG5zL0OwlCJ4y5KznF3EUNDDrinwiyLZRzOXtlBbK5ITHFGLp8Q0R6ab6mS7enI2cFrxOyHvOCFaT1HThS1krjCwqWeurCkk+willhCC+RSZnRXBiZaC5RXRIZYKp2lyfrHwiKPKR0JDzrdU2EFgpidawlFDR6FgXUMNa+g1FY3bUQh2cLCwosRdnuQTS/S+JVrGLeWIvtQUvONJxlqSQYYKpwoN2kaocLjdVsis4Mk80ESF2YpSkzwldjHkjFCUutI/r+EHDU8oCs6yzL3PhWiEooZdFMkymlas4AcI3KmoMMNSQ3tHzjGWCrcJJdYyZC7QFGwjRL9p+MrRkAGWzIaWCn9W0F3TsK01c2ZvQw0byvxuQU0r1lM0qJO7wW0kRIMdDTtXEdzi4VIh+EoIHm0mWtAtpCixlabgn83fKTI7anJe9ST7WIK1DMGpQmYeA58ImV6ezOGOzK2Kgq01pd60cKWiUi9Lievb/0vIDPHQ05Kzt4ddPckQBQtoaurjyHnek/nKzpQLrVgKPjIkh2v4uyezpv+Xoo7fPFXaGFp1vaLKxQ4uUpQQS5VuQs7BCq4xRJv7fwpVvvFEB3j+620haOuocqMhWd6TTPAEx+mdFNGHdranFe95WrWmIvlY4F1Dle2ECgc6cto7SryuqGGGha0tFQ5V53migUKmg6XKAo4qS3mik+0OZpAhOLeZKicacgaYcyx5hypYQE02ZA4xi/pNhOQxR4klNKyqacj+mpxnLTnnGSo85++3ZCZq6lrZkXlGEX3o+C9FieccJbZWVFjC0Yo1FZnJhoYMFoI1hEZ9r6hwg75HwzBNhbZCdJEfJwTPGzJvaKImw1yYX1HDAmpXR+ZJQ/SmgqMNVQb5vgamGwLtt7VwvP7Qk1xpiM5x5Cyv93E06MZmgs0Nya2azIKOYKCGBQQW97RmhKNKF02JZqHEJ4o58qp7X5EcZmc56trXEqzjCBZ1MFGR87Ql2tSTs6CGxS05PTzRQorkbw7aKoKXFDXsYW42VJih/q+FP2BdTzDTwVqOYB13liM50vG7wy28qagyuIXMeQI/Oqq8bcn5wJI50xH00CRntyfpL1T4hydYpoXgNiFzoIUTDZnLNRzh4TBHwbYGDvZkxmlyJloyr6tRihpeUG94GnKtIznREF0tzJG/OOr73JBcrSh1k6WuTprgLU+mnSGnv6Zge0NNz+kTDdH8nuAuTdJDCNb21LCiIuqlYbqGzT3RAoZofQfjFazkqeNWdYaGvYTM001EW2oKPvVk1ldUGSgUtHFwjKM1h9jnFcmy5lChoLNaQMGGDsYbKixlaMBmmsx1QjCfflwTfO/gckW0ruZ3jugKR3R5W9hGUWqCgxuFgsuaCHorotGKzGaeZB9DMsaTnKCpMtwTvOzhYk0rdrArKCqcaWmVk1+F372ur1YkKxgatI8Qfe1gIX9wE9FgS8ESmuABIXnRUbCapcKe+nO7slClSZFzpV/LkLncEb1qiO42fS3R855Su2mCLh62t1SYZZYVmKwIHjREF2uihTzB20JOkz7dkxzYQnK0UOU494wh+VWRc6Un2kpTaVgLDFEkJ/uhzRcI0YKGgpGWOlocBU/a4fKoJ/pEaNV6jip3+Es9VXY078rGnmAdf7t9ylPXS34RBSuYPs1UecZTU78WanhBCHpZ5sAoTz0LGZKjPf9TRypqWEiTvOFglL1fCEY3wY/++rbk7C8bWebA6p6om6PgOL2kp44TFJlVNBXae2rqqdZztOJpT87GQsE9jqCPIe9VReZuQ/CIgacsyZdCpIScSYqcZk8r+nsyCzhyfhOqHGOIvrLknC8wTpFcaYiGC/RU1NRbUeUpocQOnkRpGOrIOcNRx+1uA0UrzhSSt+VyS3SJpnFWkzNDqOFGIWcfR86DnmARTQ1HKIL33ExPiemeOhYSSjzlSUZZuE4TveoJLnBUOFof6KiysCbnAEcZgcUNTDOwkqWu3RWtmGpZwlHhJENdZ3miGz0lJlsKnjbwqSHQjpxnFDlTLLwqJPMZMjd7KrzkSG7VsxXBZE+F8YZkb01Oe00yyRK9psh5SYh29ySPKBo2ylNht7ZkZnsKenjKNJu9PNEyZpaCHv4Kt6RQsLvAVp7M9kIimmCUwGeWqLMmGuIotYMmWNpSahkhZw9FqZsVnKJhsjAHvtHMsTM9fCI06Dx/u3vfUXCqfsKRc4oFY2jMsoo/7DJDwZ1CsIKnJu+J9ldkpmiCxQx1rWjI+T9FwcWWzOuaYH0Hj7klNRVWEQpmaqosakiGNTFHdjS/qnUdmf0NJW5xsL0HhimCCZZSRzmSPTXJQ4aaztAwtZnoabebJ+htCaZ7Cm535ByoqXKbX1WRc4Eh2MkRXWzImVc96Cj4VdOKVxR84VdQsIUM8Psoou2byVHyZFuq7O8otbSQ2UAoeEWTudATLGSpZzVLlXVkPU2Jc+27lsw2jmg5T5VhbeE3BT083K9WsTTkFU/Osi0rC5lRlpwRHUiesNS0sOvmqGML1aRbPAxTJD9ZKtxuob+hhl8cwYGWpJ8nub7t5p6coYbMovZ1BTdaKn1jYD6h4GFDNFyT/Kqe1XCXphXHOKLZmuRSRdBPEfVUXQzJm5YGPGGJdvAEr7hHNdGZnuBvrpciGmopOLf5N0uVMy0FfYToJk90uUCbJupaVpO53UJXR2bVpoU00V2KOo4zMFrBd0Jtz2pa0clT5Q5L8IpQ177mWQejPMEJhuQjS10ref6HHjdEhy1P1EYR7GtO0uSsKJQYLiTnG1rVScj5lyazpqWGl5uBbRWl7m6ixGOOnEsMJR7z8J0n6KMnCdxhiNYQCoZ6CmYLnO8omC3MkW3bktlPmEt/VQQHejL3+dOE5FlPdK/Mq8hZxxJtLyRrepLThYKbLZxkSb5W52vYxNOaOxUF0yxMUPwBTYqCzy01XayYK0sJyWBLqX0MwU5CzoymRzV0EjjeUeLgDpTo6ij42ZAzvD01dHUUTPLU96MdLbBME8nFBn7zJCMtJcZokn8YoqU0FS5WFKyniHobguMcmW8N0XkWZjkyN3hqOMtS08r+/xTBwpZSZ3qiVRX8SzMHHjfUNFjgHEPmY9PL3ykEzxkSre/1ZD6z/NuznuB0RcE1TWTm9zRgfUWVJiG6yrzgmWPXC8EAR4Wxhlad0ZbgQyEz3pG5RVEwwDJH2mgKpjcTiCOzn1lfUWANFbZ2BA8balnEweJC9J0iuaeZoI+ippFCztEKVvckR2iice1JvhVytrQwUAZpgsubCPaU7xUe9vWnaOpaSBEspalykhC9bUlOMpT42ZHca6hyrqKmw/wMR8H5ZmdFoBVJb03O4UL0tSNnvIeRmkrLWqrs78gcrEn2tpcboh0UPOW3UUR9PMk4T4nnNKWmCjlrefhCwxRNztfmIQVdDElvS4m1/WuOujoZCs5XVOjtKPGokJzsYCtFYoWonSPT21DheU/wWhM19FcElwqNGOsp9Q8N/cwXaiND1MmeL1Q5XROtYYgGeFq1aTMsoMmcrKjQrOFQTQ1fmBYhmW6o8Jkjc7iDJRTBIo5kgJD5yMEYA3srCg7VFKwiVJkmRCc5ohGOKhsYMn/XBLdo5taZjlb9YAlGWRimqbCsoY7HFAXLa5I1HPRxMMsQDHFkWtRNniqT9UEeNjcE7RUlrCJ4R2CSJuqlKHWvJXjAUNcITYkenuBRB84TbeepcqTj3zZyFJzgYQdHnqfgI0ddUwS6GqWpsKWhjq9cV0vBAEMN2znq+EBfIWT+pClYw5xsTlJU6GeIBsjGmmANTzJZiIYpgrM0Oa8ZMjd7NP87jxhqGOhJlnQtjuQpB+8aEE00wZFznSJPyHxgH3HkPOsJFvYk8zqCHzTs1BYOa4J3PFU+UVRZxlHDM4YavlNUuMoRveiZA2d7grMNc2g+RbSCEKzmgYsUmWmazFJyoiOZ4KnyhKOGRzWJa0+moyV4TVHDzn51Awtqaphfk/lRQ08FX1iiqxTB/kLwd0VynKfEvI6cd4XMV5bMhZ7gZUWVzYQ6Nm2BYzxJbw3bGthEUUMfgbGeorae6DxHtJoZ6alhZ0+ytiVoK1R4z5PTrOECT/SugseEOlb1MMNR4VRNcJy+V1Hg9ONClSZFZjdHlc6W6FBLdJja2MC5hhpu0DBYEY1TFGwiFAxRRCsYkiM9JRb0JNMVkW6CZYT/2EiTGWmo8k+h4FhDNE7BvppoTSFnmCV5xZKzvcCdDo7VVPnIU+I+Rc68juApC90MwcFCsJ5hDqxgScYKreruyQwTqrzoqDCmhWi4IbhB0Yrt3RGa6GfDv52rKXWhh28dyZaWUvcZeMTBaZoSGyiCtRU5J8iviioHaErs7Jkj61syVzTTgOcUOQ8buFBTYWdL5g3T4qlpe0+wvD63heAXRfCCIed9RbCsp2CiI7raUOYOTU13N8PNHvpaGvayo4a3LLT1lDrVEPT2zLUlheB1R+ZTRfKWJ+dcocLJfi11vyJ51lLqJ0WD7tRwryezjiV5W28uJO9qykzX8JDe2lHl/9oyBwa2UMfOngpXCixvKdXTk3wrsKmiVYdZIqsoWEERjbcUNDuiaQomGoIbFdEHmsyWnuR+IeriKDVLnlawlyNHKwKlSU631PKep8J4Q+ayjkSLKYLhalNHlYvttb6fHm0p6OApsZ4l2VfdqZkjuysy6ysKLlckf1KUutCTs39bmCgEyyoasIWlVaMF7mgmWtBT8Kol5xpH9IGllo8cJdopcvZ2sImlDmMIbtDk3KIpeNiS08lQw11NFPTwVFlPP6pJ2gvRfI7gQUfmNAtf6Gs0wQxDsKGlVBdF8rCa3jzdwMaGHOsItrZk7hAyOzpK9VS06j5F49b0VNGOOfKs3lDToMsMBe9ZWtHFEgxTJLs7qrygKZjUnmCYoeAqeU6jqWuLJup4WghOdvCYJnrSkSzoyRkm5M2StQwVltPkfCAk58tET/CSg+8MUecmotMEnhBKfWBIZsg2ihruMJQaoIm+tkTLKEqspMh00w95gvFCQRtDwTT1gVDDSEVdlwqZfxoQRbK0g+tbiBZxzKlpnpypejdDwTaeOvorMk/IJE10h9CqRe28hhLbe0pMsdSwv4ZbhKivo2BjDWfL8UKJgeavwlwb5KlwhyE4u4XkGE2ytZCznKLCDZZq42VzT8HLCrpruFbIfOIINmh/qCdZ1ZBc65kLHR1Bkyf5zn6pN3SvGKIlFNGplhrO9QSXanLOMQTLCa0YJCRrCZm/CZmrLTm7WzCK4GJDiWUdFeYx1LCFg3NMd0XmCuF3Y5rITLDUsYS9zoHVzwnJoYpSTQoObyEzr4cFBNqYTopoaU/wkyLZ2lPhX/5Y95ulxGTV7KjhWrOZgl8MyUUafjYraNjNU1N3IWcjT5WzWqjwtoarHSUObGYO3GCJZpsBlnJGPd6ZYLyl1GdCA2625IwwJDP8GUKymbzuyPlZlvTUsaUh5zFDhRWFzPKKZLAlWdcQbObgF9tOqOsmB1dqcqYJmWstFbZRRI9poolmqiLnU0POvxScpah2iSL5UJNzgScY5+AuIbpO0YD3NCW+dLMszFSdFCWGqG6eVq2uYVNDdICGD6W7EPRWZEY5gpsE9rUkS3mijzzJnm6UpUFXG1hCUeVoS5WfNcFpblELL2qqrCvMvRfd45oalvKU2tiQ6ePJOVMRXase9iTtLJztPxJKLWpo2CRDcJwn2sWSLKIO1WQWNTCvpVUvOZhgSC40JD0dOctaSqzkCRbXsKlb11Oip6PCJ0IwSJM31j3akRxlP7Rwn6aGaUL0qiLnJkvB3xWZ2+Q1TfCwpQH3G0o92UzmX4o/oJNQMMSQc547wVHhdk+VCw01DFYEnTxzZKAm74QmeNNR1w6WzEhNK15VJzuCdxQ53dRUDws5KvwgBMOEgpcVNe0hZI6RXT1Jd0cyj5nsaEAHgVmGaJIlWdsc5Ui2ElrRR6jrRAttNMEAIWrTDFubkZaok7/AkzfIwfuWVq0jHzuCK4QabtLUMVPB3kJ0oyHTSVFlqMALilJf2Rf8k5aaHtMfayocLBS8L89oKoxpJvnAkDPa0qp5DAUTHKWmCcnthlou8iCKaFFLHWcINd1nyIwXqrSxMNmSs6KmoL2QrKuWtlQ5V0120xQ5vRyZS1rgFkWwhiOwiuQbR0OOVhQM9iS3tiXp4RawRPMp5tDletOOBL95MpM01dZTBM9pkn5qF010rIeHFcFZhmSGpYpTsI6nwhqe5C9ynhlpp5ophuRb6WcJFldkVnVEwwxVfrVkvnWUuNLCg5bgboFHPDlDPDmnK7hUrWiIbjadDclujlZcaokOFup4Ri1kacV6jmrrK1hN9bGwpKEBQ4Q6DvIUXOmo6U5LqQM6EPyiKNjVkPnJkDPNEaxhiFay5ExW1NXVUGqcpYYdPcGiCq7z/TSlbhL4pplWXKd7NZO5QQFrefhRQW/NHOsqcIglc4UhWklR8K0QzbAw08CBDnpbgqXdeD/QUsM4RZXDFBW6WJKe/mFPdH0LtBgiq57wFLzlyQzz82qYx5D5WJP5yVJDW01BfyHnS6HKO/reZqId1WGa4Hkh2kWodJ8i6KoIPlAj2hPt76CzXsVR6koPRzWTfKqIentatYpQw2me4AA3y1Kind3SwoOKZDcFXTwl9tWU6mfgRk9d71sKtlNwrjnYw5tC5n5LdKiGry3JKNlHEd3oaMCFHrazBPMp/uNJ+V7IudcSbeOIdjUEdwl0VHCOZo5t6YluEuaC9mQeMgSfOyKnYGFHcIeQ84yQWbuJYJpZw5CzglDH7gKnWqqM9ZTaXcN0TeYhR84eQtJT76JJ1lREe7WnnvsMmRc9FQ7SBBM9mV3lCUdmHk/S2RAMt0QjFNFqQpWjDPQ01DXWUdDBkXziKPjGEP3VP+zIWU2t7im41FOloyWzn/L6dkUy3VLDaZ6appgDLHPjJEsyvJngWEPUyVBiAaHCTEXwrLvSEbV1e1gKJniicWorC1MUrVjB3uDhJE/wgSOzk1DXpk0k73qCM8xw2UvD5kJmDUfOomqMpWCkJRlvKXGmoeBm18USjVIk04SClxTB6YrgLAPLWYK9HLUt5cmc0vYES8GnTeRc6skZbQkWdxRsIcyBRzx1DbTk9FbU0caTPOgJHhJKnOGIVhQqvKmo0llRw9sabrZkDtdg3PqaKi9oatjY8B+G371paMg6+mZFNNtQ04mWBq3rYLOmtWWQp8KJnpy9DdFensyjdqZ+yY40VJlH8wcdLzC8PZnvHMFUTZUrDTkLyQaGus5X5LzpYAf3i+e/ZlhqGqWhh6Ou6xTR9Z6oi5AZZtp7Mj2EEm8oSpxiYZCHU/1fbGdNNNRRoZMhmilEb2gqHOEJDtXkHK/JnG6IrvbPCwV3NhONVdS1thBMs1T4QOBcTWa2IzhMk2nW5Kyn9tXUtpv9RsG2msxk+ZsQzRQacJncpgke0+T8y5Fzj8BiGo7XlJjaTIlpQs7KFjpqGnKuoyEPeIKnFMkZHvopgh81ySxNFWvJWcKRs70j2FOT012IllEEO1n4pD1513Yg2ssQPOThOkvyrqHUdEXOSEsihmBbTbKX1kLBPWqWkLOqJbjB3GBIZmoa8qWl4CG/iZ7oiA72ZL7TJNeZUY7kFQftDcHHluBzRbCegzMtrRjVQpX2lgoPKKLJAkcbMl01XK2p7yhL8pCBbQ3BN2avJgKvttcrWDK3CiUOVxQ8ZP+pqXKyIxnmBymCg5vJjNfkPK4+c8cIfK8ocVt7kmfd/I5SR1hKvCzUtb+lhgc00ZaO6CyhIQP1Uv4yIZjload72PXX0OIJvnFU+0Zf6MhsJwTfW0r0UwQfW4LNLZl5HK261JCZ4qnBaAreVAS3WrjV0LBnNDUNNDToCEeFfwgcb4gOEqLRhirWkexrCEYKVV711DLYEE1XBEsp5tpTGjorkomKYF9FDXv7fR3BGwbettSxnyL53MBPjsxDZjMh+VUW9NRxq1DhVk+FSxQcaGjV9Pawv6eGByw5qzoy7xk4RsOShqjJwWKe/1pEEfzkobeD/dQJmpqedcyBTy2sr4nGNRH0c0SPWTLrqAc0OQcb/gemKgqucQT7ySWKCn2EUotoCvpZct7RO2sy/QW0IWcXd7pQRQyZVwT2USRO87uhjioTLKV2brpMUcMQRbKH/N2T+UlTpaMls6cmc6CCNy3JdYYSUzzJQ4oSD3oKLncULOiJvjBEC2oqnCJkJluCYy2ZQ5so9YYlZ1VLlQU1mXEW1jZERwj/MUSRc24TdexlqLKfQBtDTScJUV8FszXBEY5ktpD5Ur9hYB4Nb1iikw3JoYpkKX+RodRKFt53MMuRnKSpY31PwYaGaILh3wxJGz9TkTPEETxoCWZrgvOlmyMzxFEwVJE5xZKzvyJ4WxEc16Gd4Xe3Weq4XH2jKRikqOkGQ87hQnC7wBmGYLAnesX3M+S87eFATauuN+Qcrh7xIxXJbUIdMw3JGE3ylCWzrieaqCn4zhGM19TQ3z1oH1AX+pWEqIc7wNGAkULBo/ZxRaV9NNyh4Br3rCHZzbzmSfawBL0dNRwpW1kK9mxPXR9povcdrGSZK9c2k0xwFGzjuniCtRSZCZ6ccZ7gaktmgAOtKbG/JnOkJrjcQTdFMsxRQ2cLY3WTIrlCw1eWKn8R6pvt4GFDso3QoL4a3nLk3G6JrtME3dSenpx7PNFTmga0EaJTLQ061sEeQoWXhSo9LTXsaSjoJQRXeZLtDclbCrYzfzHHeaKjHCVOUkQHO3JeEepr56mhiyaYYKjjNU+Fed1wS5VlhWSqI/hYUdDOkaxiKehoyOnrCV5yBHtbWFqTHCCwtpDcYolesVR5yUzTZBb3RNMd0d6WP+SvhuBmRcGxnuQzT95IC285cr41cLGQ6aJJhmi4TMGempxeimBRQw1tFKV+8jd6KuzoSTqqDxzRtpZkurvKEHxlqXKRIjjfUNNXQsNOsRScoWFLT+YeRZVD3GRN0MdQcKqQjHDMrdGGVu3iYJpQx3WGUvfbmxwFfR20WBq0oYY7LMFhhgYtr8jpaEnaOzjawWWaTP8mMr0t/EPDPoqcnxTBI5o58L7uoWnMrpoqPwgVrlAUWE+V+TQl9rawoyP6QGAlQw2TPRX+YSkxyBC8Z6jhHkXBgQL7WII3DVFnRfCrBfxewv9D6xsyjys4VkhWb9pUU627JllV0YDNHMku/ldNMMXDEo4aFnAkk4U6frNEU4XgZUPmEKHUl44KrzmYamjAbh0JFvGnaTLPu1s9jPCwjFpYiN7z1DTOk/nc07CfDFzmCf7i+bfNHXhDtLeBXzTBT5rkMvWOIxpl4EMh2LGJBu2syDnAEx2naEhHDWMMzPZEhygyS1mS5RTJr5ZkoKbEUoYqr2kqdDUE8ztK7OaIntJkFrIECwv8LJTaVx5XJE86go8dFeZ3FN3rjabCAYpoYEeC9zzJVULBbmZhDyd7ko09ydpNZ3nm2Kee4FPPXHnYEF1nqOFEC08LUVcDvYXkJHW8gTaKCk9YGOeIJhqiE4ToPEepdp7IWFjdwnWaufGMwJJCMtUTTBBK9BGCOy2tGGrJTHIwyEOzp6aPzNMOtlZkDvcEWpP5SVNhfkvDxhmSazTJXYrM9U1E0xwFVwqZQwzJxw6+kGGGUj2FglGGmnb1/G51udRSMNlTw6GGnCcUwVcOpmsqTHa06o72sw1RL02p9z0VbnMLOaIX3QKaYKSCFQzBKEUNHTSc48k53RH9wxGMtpQa5KjjW0W0n6XCCCG4yxNNdhQ4R4l1Ff+2sSd6UFHiIEOyqqFgT01mEUMD+joy75jPhOA+oVVLm309FR4yVOlp4RhLiScNmSmaYF5Pw0STrOIoWMSR2UkRXOMp+M4SHW8o8Zoi6OZgjKOaFar8zZDzkWzvKOjkKBjmCXby8JahhjXULY4KlzgKLvAwxVGhvyd4zxB1d9T0piazmKLCVZY5sKiD0y2ZSYrkUEPUbIk+dlQ4SJHTR50k1DPaUWIdTZW9NJwnJMOECgd7ou/MnppMJ02O1VT4Wsh85MnZzcFTngpXGKo84qmwgKbCL/orR/SzJ2crA+t6Mp94KvxJUeIbT3CQu1uIdlQEOzlKfS3UMcrTiFmOuroocrZrT2AcmamOKg8YomeEKm/rlT2sociMaybaUlFhuqHCM2qIJ+rg4EcDFymiDSxzaHdPcpE62pD5kyM5SBMoA1PaUtfIthS85ig1VPiPPYXgYEMNk4Qq7TXBgo7oT57gPUdwgCHzhIVFPFU6OYJzHAX9m5oNrVjeE61miDrqQ4VSa1oiURTsKHC0IfjNwU2WzK6eqK8jWln4g15TVBnqmDteCJ501PGAocJhhqjZdtBEB6lnhLreFJKxmlKbeGrqLiSThVIbCdGzloasa6lpMQXHCME2boLpJgT7yWaemu6wBONbqGNVRS0PKIL7LckbjmQtR7K8I5qtqel+T/ChJTNIKLjdUMNIRyvOEko9YYl2cwQveBikCNawJKcLBbc7+JM92mysNvd/Fqp8a0k6CNEe7cnZrxlW0wQXaXjaktnRwNOGZKYiONwS7a1JVheq3WgJHlQUGKHKmp4KAxXR/ULURcNgoa4zhKSLpZR3kxRRb0NmD0OFn+UCS7CzI1nbP6+o4x47QZE5xRCt3ZagnYcvmpYQktXdk5YKXTzBC57kKEe0VVuiSYqapssMS3C9p2CKkHOg8B8Pa8p5atrIw3qezIWanMGa5HRDNF6RM9wcacl0N+Q8Z8hsIkSnaIIdHRUOEebAPy1zbCkhM062FCJtif7PU+UtoVXzWKqM1PxXO8cfdruhFQ/a6x3JKYagvVDhQEtNiyiiSQ7OsuRsZUku0CRNDs4Sog6KKjsZgk2bYJqijgsEenoKeniinRXBn/U3lgpPdyDZynQx8IiioMnCep5Ky8mjGs6Wty0l1hUQTcNWswS3WRp2kCNZwJG8omG8JphPUaFbC8lEfabwP7VtM9yoaNCAjpR41VNhrD9LkbN722v0CoZMByFzhaW+MyzRYEWFDQwN2M4/JiT76PuljT3VU/A36eaIThb+R9oZGOAJ9tewkgGvqOMNRWYjT/Cwu99Q8LqDE4TgbLWxJ1jaDDAERsFOFrobgjUsBScaguXU8kKm2RL19tRypSHnHNlHiIZqgufs4opgQdVdwxBNNFBR6kVFqb8ogimOzB6a6HTzrlDHEpYaxjiiA4TMQobkDg2vejjfwJGWmnbVFAw3H3hq2NyQfG7hz4aC+w3BbwbesG0swYayvpAs6++Ri1Vfzx93mFChvyN5xVHTS+0p9aqCAxyZ6ZacZyw5+7uuQkFPR9DDk9NOiE7X1PCYJVjVUqq7JlrHwWALF5nfHNGjApdpqgzx5OwilDhCiDYTgnc9waGW4BdLNNUQvOtpzDOWHDH8D7TR/A/85KljEQu3NREc4Pl/6B1Hhc8Umb5CsKMmGC9EPcxoT2amwHNCmeOEnOPbklnMkbOgIvO5UMOpQrS9UGVdt6iH/fURjhI/WOpaW9OKLYRod6HCUEdOX000wpDZQ6hwg6LgZfOqo1RfT/CrJzjekXOGhpc1VW71ZLbXyyp+93ILbC1kPtIEYx0FIx1VDrLoVzXRKRYWk809yYlC9ImcrinxtabKnzRJk3lAU1OLEN1j2zrYzr2myHRXJFf4h4QKT1qSTzTB5+ZNTzTRkAxX8FcLV2uS8eoQQ2aAkFzvCM72sJIcJET3WPjRk5wi32uSS9rfZajpWEvj9hW42F4o5NytSXYy8IKHay10VYdrcl4SkqscrXpMwyGOgtkajheSxdQqmpxP1L3t4R5PqasFnrQEjytq6qgp9Y09Qx9o4S1FzhUCn1kyHSzBWLemoSGvOqLNhZyBjmCaAUYpMgt4Ck7wBBMMwWKWgjsUwTaGVsxWC1mYoKiyqqeGKYqonSIRQ3KIkHO0pmAxTdBHkbOvfllfr+AA+7gnc50huVKYK393FOyg7rbPO/izI7hE4CnHHHnJ0ogNPRUGeUpsrZZTBJcrovUcJe51BPsr6GkJdhCCsZ6aTtMEb2pqWkqeVtDXE/QVggsU/Nl86d9RMF3DxvZTA58agu810RWawCiSzzXBeU3MMW9oyJUedvNEvQyNu1f10BSMddR1vaLCYpYa/mGocLSiYDcLbQz8aMn5iyF4xBNMs1P0QEOV7o5gaWGuzSeLue4tt3ro7y4Tgm4G/mopdZgl6q0o6KzJWE3mMksNr3r+a6CbT8g5wZNzT9O7fi/zpaOmnz3BRoqos+tv9zMbdpxsqDBOEewtJLt7cg5wtKKbvldpSzRRCD43VFheCI7yZLppggMVBS/KMAdHODJvOwq2NQSbKKKPLdFWQs7Fqo+mpl01JXYRgq8dnGLhTiFzqmWsUMdpllZdbKlyvSdYxhI9YghOtxR8LgSLWHK62mGGVoxzBE8LNWzqH9CUesQzFy5RQzTc56mhi6fgXEWwpKfE5Z7M05ZgZUPmo6auiv8YKzDYwWBLMErIbKHJvOwIrvEdhOBcQ9JdU1NHQ7CXn2XIDFBKU2WAgcX9UAUzDXWd5alwuyJ41Z9rjKLCL4aCp4WarhPm2rH+SaHUYE001JDZ2ZAzXPjdMpZWvC9wmqIB2lLhQ01D5jO06hghWMndbM7yRJMsoCj1vYbnFQVrW9jak3OlEJ3s/96+p33dEPRV5GxiqaGjIthUU6FFEZyqCa5qJrpBdzSw95IUnOPIrCUUjRZQFrbw5PR0R1qiYx3cb6nrWUMrBmmiBQxVHtTew5ICP/ip6g4hed/Akob/32wvBHsIOX83cI8hGeNeNPCIkPmXe8fPKx84OMSRM1MTdXSwjCZ4S30jVGhvqTRak/OVhgGazHuOCud5onEO1lJr6ecVyaOK6H7zqlBlIaHE0oroCgfvGJIdPcmfLNGLjpz7hZwZQpUbFME0A1cIJa7VNORkgfsMBatbKgwwJM9bSvQXeNOvbIjelg6WWvo5kvbKaJJNHexkKNHL9xRyFlH8Ti2riB5wVPhUk7nGkJnoCe428LR/wRGdYIlmWebCyxou1rCk4g/ShugBDX0V0ZQWkh0dOVsagkM0yV6OoLd5ye+pRlsCr0n+KiQrGuq5yJDzrTAXHtLUMduTDBVKrSm3eHL+6ijxhFDX9Z5gVU/wliHYTMiMFpKLNMEywu80wd3meoFmt6VbRMPenhrOc6DVe4pgXU8DnnHakLOIIrlF4FZPIw6R+zxBP0dyq6OOZ4Q5sLKCcz084ok+VsMMyQhNZmmBgX5xIXOEJTmi7VsGTvMTNdHHhpzdbE8Du2oKxgvBqQKdDDnTFOylCFaxR1syz2iqrOI/FEpNc3C6f11/7+ASS6l2inq2ciTrCCzgyemrCL5SVPjQkdPZUmGy2c9Sw9FtR1sS30RmsKPCS4rkIC/2U0MduwucYolGaPjKEyhzmiPYXagyWbYz8LWBDdzRimAXzxx4z8K9hpzlhLq+NiQ97HuKorMUfK/OVvC2JfiHUPCQI/q7J2gjK+tTDNxkCc4TMssqCs4TGtLVwQihyoAWgj9bosU80XGW6Ac9TJGziaUh5+hnFcHOnlaM1iRn29NaqGENTTTSUHCH2tWTeV0osUhH6psuVLjRUmGWhm6OZEshGeNowABHcJ2Bpy2ZszRcKkRXd2QuKVEeXnbfaEq825FguqfgfE2whlChSRMdron+LATTPQ2Z369t4B9C5gs/ylzv+CMmepIDPclFQl13W0rspPd1JOcbghGOEutqCv5qacURQl3dDKyvyJlqKXGPgcM9FfawJAMVmdcspcYKOZc4GjDYkFlK05olNMHyHn4zFNykyOxt99RkHlfwmiHo60l2EKI+mhreEKp080Tbug08BVPcgoqC5zWt+NLDTZ7oNSF51N1qie7Va3uCCwyZbkINf/NED6jzOsBdZjFN8oqG3wxVunqCSYYKf3EdhJyf9YWGf7tRU2oH3VHgPr1fe5J9hOgHd7xQ0y7qBwXr23aGErP0cm64JVjZwsOGqL+mhNgZmhJLW2oY4UhedsyBgzrCKrq7BmcpNVhR6jBPq64Vgi+kn6XE68pp8J5/+0wRHGOpsKenQn9DZntPzjRLZpDAdD2fnSgkG9tmIXnUwQ6WVighs7Yi2MxQ0N3CqYaCXkJ0oyOztMDJjmSSpcpvlrk0RMMOjmArQ04PRV1DO1FwhCVaUVPpKUM03JK5SxPsIWRu8/CGHi8UHChiqGFDTbSRJWeYUDDcH6vJWUxR4k1FXbMUwV6e4AJFXS8oMqsZKqzvYQ9DDQdZckY4aGsIhtlubbd2r3j4QBMoTamdPZk7O/Bf62lacZwneNjQoGcdVU7zJOd7ghsUHOkosagic6cnWc8+4gg285R6zZP5s1/LUbCKIznTwK36PkdwlOrl4U1LwfdCCa+IrvFkmgw1PCAUXKWo0sURXWcI2muKJlgyFzhynCY4RBOsqCjoI1R5zREco0n2Vt09BQtYSizgKNHfUmUrQ5UOCh51BFcLmY7umhYqXKQomOop8bUnWNNQcIiBcYaC6xzMNOS8JQQfeqKBmmglB+97ok/lfk3ygaHSyZaCRTzRxQo6GzLfa2jWBPepw+UmT7SQEJyiyRkhBLMVOfcoMjcK0eZChfUNzFAUzCsEN5vP/X1uP/n/aoMX+K+nw/Hjr/9xOo7j7Pju61tLcgvJpTWXNbfN5jLpi6VfCOviTktKlFusQixdEKWmEBUKNaIpjZRSSOXSgzaaKLdabrm1/9nZ+/f+vd/vz/v9+Xy+zZ7PRorYoZqyLrCwQdEAixxVOEXNNnjX2nUSRlkqGmWowk8lxR50JPy9Bo6qJXaXwNvREBvnThPEPrewryLhcAnj5WE15Fqi8W7R1sAuEu86S4ENikItFN4xkv9Af4nXSnUVcLiA9xzesFpivRRVeFKtsMRaKBhuSbjOELnAUtlSQUpXgdfB4Z1oSbnFEetbQ0IrAe+Y+pqnDcEJFj6S8LDZzZHwY4e3XONNlARraomNEt2bkvGsosA3ioyHm+6jCMbI59wqt4eeara28IzEmyPgoRaUOEDhTVdEJhmCoTWfC0p8aNkCp0oYqih2iqGi4yXeMkOsn4LdLLnmKfh/YogjNsPebeFGR4m9BJHLzB61XQ3BtpISfS2FugsK9FAtLWX1dCRcrCnUp44CNzuCowUZmxSRgYaE6Za0W2u/E7CVXCiI/UOR8aAm1+OSyE3mOUcwyc1zBBeoX1kiKy0Zfxck1Gsyulti11i83QTBF5Kg3pDQThFMVHiPSlK+0cSedng/VaS8bOZbtsBcTcZAR8JP5KeqQ1OYKAi20njdNNRpgnsU//K+JnaXJaGTomr7aYIphoRn9aeShJWKEq9LcozSF7QleEfDI5LYm5bgVkFkRwVDBCVu0DDIkGupo8TZBq+/pMQURYErJQmPKGKjNDkWOLx7Jd5QizdUweIaKrlP7SwJDhZvONjLkOsBBX9UpGxnydhXkfBLQ8IxgojQbLFnJf81JytSljclYYyEFyx0kVBvKWOFJmONpshGAcsduQY5giVNCV51eOdJYo/pLhbvM0uDHSevNKRcrKZIqnCtJeEsO95RoqcgGK4ocZcho1tTYtcZvH41pNQ7vA0WrhIfOSraIIntIAi+NXWCErdbkvrWwjRLrt0NKUdL6KSOscTOdMSOUtBHwL6OLA0vNSdynaWQEnCpIvKaIrJJEbvHkmuNhn6OjM8VkSGSqn1uYJCGHnq9I3aLhNME3t6GjIkO7xrNFumpyTNX/NrwX7CrIRiqqWijI9JO4d1iieykyfiposQIQ8YjjsjlBh6oHWbwRjgYJQn2NgSnNycmJAk3NiXhx44Sxykihxm8ybUwT1OVKySc7vi3OXVkdBJ4AyXBeksDXG0IhgtYY0lY5ahCD0ehborIk5aUWRJviMA7Xt5kyRjonrXENkm8yYqgs8VzgrJmClK20uMM3jRJ0FiQICQF9hdETlLQWRIb5ki6WDfWRPobvO6a4GP5mcOrNzDFELtTkONLh9dXE8xypEg7z8A9jkhrQ6Fhjlg/QVktJXxt4WXzT/03Q8IaQWSqIuEvloQ2mqC9Jfi7wRul4RX3pSPlzpoVlmCtI2jvKHCFhjcM3sN6lqF6HxnKelLjXWbwrpR4xzuCrTUZx2qq9oAh8p6ixCUGr78g8oyjRAtB5CZFwi80VerVpI0h+IeBxa6Zg6kWvpDHaioYYuEsRbDC3eOmC2JvGYLeioxGknL2UATNJN6hmtj1DlpLvDVmocYbrGCVJKOrg4X6DgddLA203BKMFngdJJFtFd7vJLm6KEpc5yjQrkk7M80SGe34X24nSex1Ra5Omgb71JKyg8SrU3i/kARKwWpH0kOGhKkObyfd0ZGjvyXlAkVZ4xRbYJ2irFMkFY1SwyWxr2oo4zlNiV+7zmaweFpT4kR3kaDAFW6xpSqzJay05FtYR4HmZhc9UxKbbfF2V8RG1MBmSaE+kmC6JnaRXK9gsiXhJHl/U0qM0WTcbyhwkYIvFGwjSbjfwhiJt8ZSQU+Bd5+marPMOkVkD0muxYLIfEuhh60x/J92itguihJSEMySVPQnTewnEm+620rTQEMsOfo4/kP/0ARvWjitlpSX7GxBgcMEsd3EEeYWvdytd+Saawi6aCIj1CkGb6Aj9rwhx16Cf3vAwFy5pyLhVonXzy51FDpdEblbkdJbUcEPDEFzQ8qNmhzzLTmmKWKbFCXeEuRabp6rxbvAtLF442QjQ+wEA9eL1xSR7Q0JXzlSHjJ4exq89yR0laScJ/FW6z4a73pFMEfDiRZvuvijIt86RaSFOl01riV2mD1UEvxGk/Geg5aWwGki1zgKPG9J2U8PEg8qYvMsZeytiTRXBMslCU8JSlxi8EabjwUldlDNLfzTUmCgxWsjqWCOHavYAqsknKFIO0yQ61VL5AVFxk6WhEaCAkdJgt9aSkzXlKNX2jEa79waYuc7gq0N3GDJGCBhoiTXUEPsdknCUE1CK0fwsiaylSF2uiDyO4XX3pFhNd7R4itFGc0k/ElBZwWvq+GC6szVeEoS/MZ+qylwpKNKv9Z469UOjqCjwlusicyTxG6VpNxcQ8IncoR4RhLbR+NdpGGmJWOcIzJGUuKPGpQg8rrG21dOMqQssJQ4RxH5jaUqnZuQ0F4Q+cjxLwPtpZbIAk3QTJHQWBE5S1BokoVtDd6lhqr9UpHSUxMcIYl9pojsb8h4SBOsMQcqvOWC2E8EVehqiJ1hrrAEbQxeK0NGZ0Gkq+guSRgniM23bIHVkqwx4hiHd7smaOyglyIyQuM978j4VS08J/A2G1KeMBRo4fBaSNhKUEZfQewVQ/C1I+MgfbEleEzCUw7mKXI0M3hd1EESVji8x5uQ41nxs1q4RMJCCXs7Iq9acpxn22oSDnQ/sJTxsCbHIYZiLyhY05TY0ZLIOQrGaSJDDN4t8pVaIrsqqFdEegtizc1iTew5Q4ayBDMUsQMkXocaYkc0hZua412siZ1rSXlR460zRJ5SlHGe5j801RLMlJTxtaOM3Q1pvxJ45zUlWFD7rsAbpfEm1JHxG0eh8w2R7QQVzBUw28FhFp5QZzq8t2rx2joqulYTWSuJdTYfWwqMFMcovFmSyJPNyLhE4E10pHzYjOC3huArRa571ZsGajQpQx38SBP5pyZB6lMU3khDnp0MBV51BE9o2E+TY5Ml2E8S7C0o6w1xvCZjf0HkVEHCzFoyNmqC+9wdcqN+Tp7jSDheE9ws8Y5V0NJCn2bk2tqSY4okdrEhx1iDN8cSudwepWmAGXKcJXK65H9to8jYQRH7SBF01ESUJdd0TayVInaWhLkOjlXE5irKGOnI6GSWGCJa482zBI9rCr0jyTVcEuzriC1vcr6mwFGSiqy5zMwxBH/TJHwjSPhL8+01kaaSUuMFKTcLEvaUePcrSmwn8DZrgikWb7CGPxkSjhQwrRk57tctmxLsb9sZvL9LSlyuSLlWkqOjwduo8b6Uv1DkmudIeFF2dHCgxVtk8dpIvHpBxhEOdhKk7OLIUSdJ+cSRY57B+0DgGUUlNfpthTfGkauzxrvTsUUaCVhlKeteTXCoJDCa2NOKhOmC4G1H8JBd4OBZReSRGkqcb/CO1PyLJTLB4j1q8JYaIutEjSLX8YKM+a6phdMsdLFUoV5RTm9JSkuDN8WcIon0NZMNZWh1q8C7SJEwV5HxrmnnTrf3KoJBlmCYI2ilSLlfEvlE4011NNgjgthzEua0oKK7JLE7HZHlEl60BLMVFewg4EWNt0ThrVNEVkkiTwpKXSWJzdRENgvKGq4IhjsiezgSFtsfCUq8qki5S1LRQeYQQ4nemmCkImWMw3tFUoUBZk4NOeZYEp4XRKTGa6wJjrWNHBVJR4m3FCnbuD6aak2WsMTh3SZImGCIPKNgsDpVwnsa70K31lCFJZYcwwSMFcQulGTsZuEaSdBXkPGZhu0FsdUO73RHjq8MPGGIfaGIbVTk6iuI3GFgucHrIQkmWSJdBd7BBu+uOryWAhY7+Lki9rK5wtEQzWwvtbqGhIMFwWRJsElsY4m9IIg9L6lCX0VklaPAYkfkZEGDnOWowlBJjtMUkcGK4Lg6EtoZInMUBVYLgn0UsdmCyCz7gIGHFfk+k1QwTh5We7A9x+IdJ6CvIkEagms0hR50eH9UnTQJ+2oiKyVlLFUE+8gBGu8MQ3CppUHesnjTHN4QB/UGPhCTHLFPHMFrCqa73gqObUJGa03wgbhHkrCfpEpzNLE7JDS25FMKhlhKKWKfCgqstLCPu1zBXy0J2ztwjtixBu8UTRn9LVtkmCN2iyFhtME70JHRQ1KVZXqKI/KNIKYMCYs1GUMEKbM1bKOI9LDXC7zbHS+bt+1MTWS9odA9DtrYtpbImQJ2VHh/lisEwaHqUk1kjKTAKknkBEXkbkdMGwq0dnhzLJF3NJH3JVwrqOB4Sca2hti75nmJN0WzxS6UxDYoEpxpa4htVlRjkYE7DZGzJVU72uC9IyhQL4i8YfGWSYLLNcHXloyz7QhNifmKSE9JgfGmuyLhc403Xm9vqcp6gXe3xuuv8F6VJNxkyTHEkHG2g0aKXL0MsXc1bGfgas2//dCONXiNLCX+5mB7eZIl1kHh7ajwpikyzlUUWOVOsjSQlsS+M0R+pPje/dzBXRZGO0rMtgQrLLG9VSu9n6CMXS3BhwYmSoIBhsjNBmZbgusE9BCPCP5triU4VhNbJfE+swSP27aayE8tuTpYYjtrYjMVGZdp2NpS1s6aBnKSHDsbKuplKbHM4a0wMFd/5/DmGyKrJSUaW4IBrqUhx0vyfzTBBLPIUcnZdrAkNsKR0sWRspumSns6Ch0v/qqIbBYUWKvPU/CFoyrDJGwSNFhbA/MlzKqjrO80hRbpKx0Jewsi/STftwGSlKc1JZyAzx05dhLEdnfQvhZOqiHWWEAHC7+30FuRcZUgaO5gpaIK+xsiHRUsqaPElTV40xQZQ107Q9BZE1nryDVGU9ZSQ47bmhBpLcYpUt7S+xuK/FiT8qKjwXYw5ypS2iuCv7q1gtgjhuBuB8LCFY5cUuCNtsQOFcT+4Ih9JX+k8Ea6v0iCIRZOtCT0Et00JW5UeC85Cg0ScK0k411HcG1zKtre3SeITBRk7WfwDhEvaYLTHP9le0m8By0JDwn4TlLW/aJOvGHxdjYUes+ScZigCkYQdNdEOhkiezgShqkx8ueKjI8lDfK2oNiOFvrZH1hS+tk7NV7nOmLHicGWEgubkXKdwdtZknCLJXaCpkrjZBtLZFsDP9CdxWsSr05Sxl6CMmoFbCOgryX40uDtamB7SVmXW4Ihlgpmq+00tBKUUa83WbjLUNkzDmY7cow1JDygyPGlhgGKYKz4vcV7QBNbJIgM11TUqZaMdwTeSguH6rOaw1JRKzaaGyxVm2EJ/uCIrVWUcZUkcp2grMsEjK+DMwS59jQk3Kd6SEq1d0S6uVmO4Bc1lDXTUcHjluCXEq+1OlBDj1pi9zgiXxnKuE0SqTXwhqbETW6RggMEnGl/q49UT2iCzgJvRwVXS2K/d6+ZkyUl7jawSVLit46EwxVljDZwoSQ20sDBihztHfk2yA8NVZghiXwrYHQdfKAOtzsayjhY9bY0yE2CWEeJ9xfzO423xhL5syS2TFJofO2pboHob0nY4GiAgRrvGQEDa/FWSsoaaYl0syRsEt3kWoH3B01shCXhTUWe9w3Bt44SC9QCh3eShQctwbaK2ApLroGCMlZrYqvlY3qYhM0aXpFkPOuoqJ3Dm6fxXrGwVF9gCWZagjPqznfkuMKQ8DPTQRO8ZqG1hPGKEm9IgpGW4DZDgTNriTxvFiq+Lz+0cKfp4wj6OCK9JSnzNSn9LFU7UhKZZMnYwcJ8s8yRsECScK4j5UOB95HFO0CzhY4xJxuCix0lDlEUeMdS6EZBkTsUkZ4K74dugyTXS7aNgL8aqjDfkCE0ZbwkCXpaWCKhl8P7VD5jxykivSyxyZrYERbe168LYu9ZYh86IkscgVLE7tWPKmJv11CgoyJltMEbrohtVAQfO4ImltiHEroYEs7RxAarVpY8AwXMcMReFOTYWe5iiLRQxJ5Q8DtJ8LQhWOhIeFESPGsILhbNDRljNbHzNRlTFbk2S3L0NOS6V1KFJYKUbSTcIIhM0wQ/s2TM0SRMNcQmSap3jCH4yhJZKSkwyRHpYYgsFeQ4U7xoCB7VVOExhXepo9ABBsYbvGWKXPME3lyH95YioZ0gssQRWWbI+FaSMkXijZXwgiTlYdPdkNLaETxlyDVIwqeaEus0aTcYcg0RVOkpR3CSJqIddK+90JCxzsDVloyrFd5ZAr4TBKfaWa6boEA7C7s6EpYaeFPjveooY72mjIccLHJ9HUwVlDhKkmutJDJBwnp1rvulJZggKDRfbXAkvC/4l3ozQOG9a8lxjx0i7nV4jSXc7vhe3OwIxjgSHjdEhhsif9YkPGlus3iLFDnWOFhtCZbJg0UbQcIaR67JjthoCyMEZRwhiXWyxO5QxI6w5NhT4U1WsJvDO60J34fW9hwzwlKij6ZAW9ne4L0s8C6XeBMEkd/LQy1VucBRot6QMlbivaBhoBgjqGiCJNhsqVp/S2SsG6DIONCR0dXhvWbJ+MRRZJkkuEjgDXJjFQW6SSL7GXK8Z2CZg7cVsbWGoKmEpzQ5elpiy8Ryg7dMkLLUEauzeO86CuwlSOlgYLojZWeJ9xM3S1PWfEfKl5ISLQ0MEKR8YOB2QfCxJBjrKPCN4f9MkaSsqoVXJBmP7EpFZ9UQfOoOFwSzBN4MQ8LsGrymlipcJQhmy0GaQjPqCHaXRwuCZwRbqK2Fg9wlClZqYicrIgMdZfxTQ0c7TBIbrChxmuzoKG8XRaSrIhhiyNFJkrC7oIAWMEOQa5aBekPCRknCo4IKPrYkvCDI8aYmY7WFtprgekcJZ3oLIqssCSMtFbQTJKwXYy3BY5oCh2iKPCpJOE+zRdpYgi6O2KmOAgvVCYaU4ySRek1sgyFhJ403QFHiVEmJHwtybO1gs8Hr5+BETQX3War0qZngYGgtVZtoqd6vFSk/UwdZElYqyjrF4HXUeFspIi9IGKf4j92pKGAdCYMVsbcV3kRF0N+R8LUd5PCsIGWoxDtBkCI0nKofdJQxT+LtZflvuc8Q3CjwWkq8KwUpHzkK/NmSsclCL0nseQdj5FRH5CNHSgtLiW80Of5HU9Hhlsga9bnBq3fEVltKfO5IaSTmGjjc4J0otcP7QsJUSQM8pEj5/wCuUuC2DWz8AAAAAElFTkSuQmCC\");\ +}\ +.ace-ambiance .ace_indent-guide {\ +background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNQUFD4z6Crq/sfAAuYAuYl+7lfAAAAAElFTkSuQmCC\") right repeat-y;\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); + +}); diff --git a/modules/backend/assets/vendor/ace/theme-chaos.js b/modules/backend/assets/vendor/ace/theme-chaos.js new file mode 100755 index 0000000..97ec7fb --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-chaos.js @@ -0,0 +1,156 @@ +ace.define("ace/theme/chaos",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-chaos"; +exports.cssText = ".ace-chaos .ace_gutter {\ +background: #141414;\ +color: #595959;\ +border-right: 1px solid #282828;\ +}\ +.ace-chaos .ace_gutter-cell.ace_warning {\ +background-image: none;\ +background: #FC0;\ +border-left: none;\ +padding-left: 0;\ +color: #000;\ +}\ +.ace-chaos .ace_gutter-cell.ace_error {\ +background-position: -6px center;\ +background-image: none;\ +background: #F10;\ +border-left: none;\ +padding-left: 0;\ +color: #000;\ +}\ +.ace-chaos .ace_print-margin {\ +border-left: 1px solid #555;\ +right: 0;\ +background: #1D1D1D;\ +}\ +.ace-chaos {\ +background-color: #161616;\ +color: #E6E1DC;\ +}\ +.ace-chaos .ace_cursor {\ +border-left: 2px solid #FFFFFF;\ +}\ +.ace-chaos .ace_cursor.ace_overwrite {\ +border-left: 0px;\ +border-bottom: 1px solid #FFFFFF;\ +}\ +.ace-chaos .ace_marker-layer .ace_selection {\ +background: #494836;\ +}\ +.ace-chaos .ace_marker-layer .ace_step {\ +background: rgb(198, 219, 174);\ +}\ +.ace-chaos .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #FCE94F;\ +}\ +.ace-chaos .ace_marker-layer .ace_active-line {\ +background: #333;\ +}\ +.ace-chaos .ace_gutter-active-line {\ +background-color: #222;\ +}\ +.ace-chaos .ace_invisible {\ +color: #404040;\ +}\ +.ace-chaos .ace_keyword {\ +color:#00698F;\ +}\ +.ace-chaos .ace_keyword.ace_operator {\ +color:#FF308F;\ +}\ +.ace-chaos .ace_constant {\ +color:#1EDAFB;\ +}\ +.ace-chaos .ace_constant.ace_language {\ +color:#FDC251;\ +}\ +.ace-chaos .ace_constant.ace_library {\ +color:#8DFF0A;\ +}\ +.ace-chaos .ace_constant.ace_numeric {\ +color:#58C554;\ +}\ +.ace-chaos .ace_invalid {\ +color:#FFFFFF;\ +background-color:#990000;\ +}\ +.ace-chaos .ace_invalid.ace_deprecated {\ +color:#FFFFFF;\ +background-color:#990000;\ +}\ +.ace-chaos .ace_support {\ +color: #999;\ +}\ +.ace-chaos .ace_support.ace_function {\ +color:#00AEEF;\ +}\ +.ace-chaos .ace_function {\ +color:#00AEEF;\ +}\ +.ace-chaos .ace_string {\ +color:#58C554;\ +}\ +.ace-chaos .ace_comment {\ +color:#555;\ +font-style:italic;\ +padding-bottom: 0px;\ +}\ +.ace-chaos .ace_variable {\ +color:#997744;\ +}\ +.ace-chaos .ace_meta.ace_tag {\ +color:#BE53E6;\ +}\ +.ace-chaos .ace_entity.ace_other.ace_attribute-name {\ +color:#FFFF89;\ +}\ +.ace-chaos .ace_markup.ace_underline {\ +text-decoration: underline;\ +}\ +.ace-chaos .ace_fold-widget {\ +text-align: center;\ +}\ +.ace-chaos .ace_fold-widget:hover {\ +color: #777;\ +}\ +.ace-chaos .ace_fold-widget.ace_start,\ +.ace-chaos .ace_fold-widget.ace_end,\ +.ace-chaos .ace_fold-widget.ace_closed{\ +background: none;\ +border: none;\ +box-shadow: none;\ +}\ +.ace-chaos .ace_fold-widget.ace_start:after {\ +content: '▾'\ +}\ +.ace-chaos .ace_fold-widget.ace_end:after {\ +content: '▴'\ +}\ +.ace-chaos .ace_fold-widget.ace_closed:after {\ +content: '‣'\ +}\ +.ace-chaos .ace_indent-guide {\ +border-right:1px dotted #333;\ +margin-right:-1px;\ +}\ +.ace-chaos .ace_fold { \ +background: #222; \ +border-radius: 3px; \ +color: #7AF; \ +border: none; \ +}\ +.ace-chaos .ace_fold:hover {\ +background: #CCC; \ +color: #000;\ +}\ +"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); + +}); diff --git a/modules/backend/assets/vendor/ace/theme-chrome.js b/modules/backend/assets/vendor/ace/theme-chrome.js new file mode 100755 index 0000000..83742aa --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-chrome.js @@ -0,0 +1,128 @@ +ace.define("ace/theme/chrome",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = false; +exports.cssClass = "ace-chrome"; +exports.cssText = ".ace-chrome .ace_gutter {\ +background: #ebebeb;\ +color: #333;\ +overflow : hidden;\ +}\ +.ace-chrome .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8;\ +}\ +.ace-chrome {\ +background-color: #FFFFFF;\ +color: black;\ +}\ +.ace-chrome .ace_cursor {\ +color: black;\ +}\ +.ace-chrome .ace_invisible {\ +color: rgb(191, 191, 191);\ +}\ +.ace-chrome .ace_constant.ace_buildin {\ +color: rgb(88, 72, 246);\ +}\ +.ace-chrome .ace_constant.ace_language {\ +color: rgb(88, 92, 246);\ +}\ +.ace-chrome .ace_constant.ace_library {\ +color: rgb(6, 150, 14);\ +}\ +.ace-chrome .ace_invalid {\ +background-color: rgb(153, 0, 0);\ +color: white;\ +}\ +.ace-chrome .ace_fold {\ +}\ +.ace-chrome .ace_support.ace_function {\ +color: rgb(60, 76, 114);\ +}\ +.ace-chrome .ace_support.ace_constant {\ +color: rgb(6, 150, 14);\ +}\ +.ace-chrome .ace_support.ace_type,\ +.ace-chrome .ace_support.ace_class\ +.ace-chrome .ace_support.ace_other {\ +color: rgb(109, 121, 222);\ +}\ +.ace-chrome .ace_variable.ace_parameter {\ +font-style:italic;\ +color:#FD971F;\ +}\ +.ace-chrome .ace_keyword.ace_operator {\ +color: rgb(104, 118, 135);\ +}\ +.ace-chrome .ace_comment {\ +color: #236e24;\ +}\ +.ace-chrome .ace_comment.ace_doc {\ +color: #236e24;\ +}\ +.ace-chrome .ace_comment.ace_doc.ace_tag {\ +color: #236e24;\ +}\ +.ace-chrome .ace_constant.ace_numeric {\ +color: rgb(0, 0, 205);\ +}\ +.ace-chrome .ace_variable {\ +color: rgb(49, 132, 149);\ +}\ +.ace-chrome .ace_xml-pe {\ +color: rgb(104, 104, 91);\ +}\ +.ace-chrome .ace_entity.ace_name.ace_function {\ +color: #0000A2;\ +}\ +.ace-chrome .ace_heading {\ +color: rgb(12, 7, 255);\ +}\ +.ace-chrome .ace_list {\ +color:rgb(185, 6, 144);\ +}\ +.ace-chrome .ace_marker-layer .ace_selection {\ +background: rgb(181, 213, 255);\ +}\ +.ace-chrome .ace_marker-layer .ace_step {\ +background: rgb(252, 255, 0);\ +}\ +.ace-chrome .ace_marker-layer .ace_stack {\ +background: rgb(164, 229, 101);\ +}\ +.ace-chrome .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgb(192, 192, 192);\ +}\ +.ace-chrome .ace_marker-layer .ace_active-line {\ +background: rgba(0, 0, 0, 0.07);\ +}\ +.ace-chrome .ace_gutter-active-line {\ +background-color : #dcdcdc;\ +}\ +.ace-chrome .ace_marker-layer .ace_selected-word {\ +background: rgb(250, 250, 255);\ +border: 1px solid rgb(200, 200, 250);\ +}\ +.ace-chrome .ace_storage,\ +.ace-chrome .ace_keyword,\ +.ace-chrome .ace_meta.ace_tag {\ +color: rgb(147, 15, 128);\ +}\ +.ace-chrome .ace_string.ace_regex {\ +color: rgb(255, 0, 0)\ +}\ +.ace-chrome .ace_string {\ +color: #1A1AA6;\ +}\ +.ace-chrome .ace_entity.ace_other.ace_attribute-name {\ +color: #994409;\ +}\ +.ace-chrome .ace_indent-guide {\ +background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\ +}\ +"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-clouds.js b/modules/backend/assets/vendor/ace/theme-clouds.js new file mode 100755 index 0000000..83d0d14 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-clouds.js @@ -0,0 +1,95 @@ +ace.define("ace/theme/clouds",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = false; +exports.cssClass = "ace-clouds"; +exports.cssText = ".ace-clouds .ace_gutter {\ +background: #ebebeb;\ +color: #333\ +}\ +.ace-clouds .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8\ +}\ +.ace-clouds {\ +background-color: #FFFFFF;\ +color: #000000\ +}\ +.ace-clouds .ace_cursor {\ +color: #000000\ +}\ +.ace-clouds .ace_marker-layer .ace_selection {\ +background: #BDD5FC\ +}\ +.ace-clouds.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #FFFFFF;\ +}\ +.ace-clouds .ace_marker-layer .ace_step {\ +background: rgb(255, 255, 0)\ +}\ +.ace-clouds .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #BFBFBF\ +}\ +.ace-clouds .ace_marker-layer .ace_active-line {\ +background: #FFFBD1\ +}\ +.ace-clouds .ace_gutter-active-line {\ +background-color : #dcdcdc\ +}\ +.ace-clouds .ace_marker-layer .ace_selected-word {\ +border: 1px solid #BDD5FC\ +}\ +.ace-clouds .ace_invisible {\ +color: #BFBFBF\ +}\ +.ace-clouds .ace_keyword,\ +.ace-clouds .ace_meta,\ +.ace-clouds .ace_support.ace_constant.ace_property-value {\ +color: #AF956F\ +}\ +.ace-clouds .ace_keyword.ace_operator {\ +color: #484848\ +}\ +.ace-clouds .ace_keyword.ace_other.ace_unit {\ +color: #96DC5F\ +}\ +.ace-clouds .ace_constant.ace_language {\ +color: #39946A\ +}\ +.ace-clouds .ace_constant.ace_numeric {\ +color: #46A609\ +}\ +.ace-clouds .ace_constant.ace_character.ace_entity {\ +color: #BF78CC\ +}\ +.ace-clouds .ace_invalid {\ +background-color: #FF002A\ +}\ +.ace-clouds .ace_fold {\ +background-color: #AF956F;\ +border-color: #000000\ +}\ +.ace-clouds .ace_storage,\ +.ace-clouds .ace_support.ace_class,\ +.ace-clouds .ace_support.ace_function,\ +.ace-clouds .ace_support.ace_other,\ +.ace-clouds .ace_support.ace_type {\ +color: #C52727\ +}\ +.ace-clouds .ace_string {\ +color: #5D90CD\ +}\ +.ace-clouds .ace_comment {\ +color: #BCC8BA\ +}\ +.ace-clouds .ace_entity.ace_name.ace_tag,\ +.ace-clouds .ace_entity.ace_other.ace_attribute-name {\ +color: #606060\ +}\ +.ace-clouds .ace_indent-guide {\ +background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-clouds_midnight.js b/modules/backend/assets/vendor/ace/theme-clouds_midnight.js new file mode 100755 index 0000000..275e9f2 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-clouds_midnight.js @@ -0,0 +1,96 @@ +ace.define("ace/theme/clouds_midnight",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-clouds-midnight"; +exports.cssText = ".ace-clouds-midnight .ace_gutter {\ +background: #232323;\ +color: #929292\ +}\ +.ace-clouds-midnight .ace_print-margin {\ +width: 1px;\ +background: #232323\ +}\ +.ace-clouds-midnight {\ +background-color: #191919;\ +color: #929292\ +}\ +.ace-clouds-midnight .ace_cursor {\ +color: #7DA5DC\ +}\ +.ace-clouds-midnight .ace_marker-layer .ace_selection {\ +background: #000000\ +}\ +.ace-clouds-midnight.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #191919;\ +}\ +.ace-clouds-midnight .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-clouds-midnight .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #BFBFBF\ +}\ +.ace-clouds-midnight .ace_marker-layer .ace_active-line {\ +background: rgba(215, 215, 215, 0.031)\ +}\ +.ace-clouds-midnight .ace_gutter-active-line {\ +background-color: rgba(215, 215, 215, 0.031)\ +}\ +.ace-clouds-midnight .ace_marker-layer .ace_selected-word {\ +border: 1px solid #000000\ +}\ +.ace-clouds-midnight .ace_invisible {\ +color: #666\ +}\ +.ace-clouds-midnight .ace_keyword,\ +.ace-clouds-midnight .ace_meta,\ +.ace-clouds-midnight .ace_support.ace_constant.ace_property-value {\ +color: #927C5D\ +}\ +.ace-clouds-midnight .ace_keyword.ace_operator {\ +color: #4B4B4B\ +}\ +.ace-clouds-midnight .ace_keyword.ace_other.ace_unit {\ +color: #366F1A\ +}\ +.ace-clouds-midnight .ace_constant.ace_language {\ +color: #39946A\ +}\ +.ace-clouds-midnight .ace_constant.ace_numeric {\ +color: #46A609\ +}\ +.ace-clouds-midnight .ace_constant.ace_character.ace_entity {\ +color: #A165AC\ +}\ +.ace-clouds-midnight .ace_invalid {\ +color: #FFFFFF;\ +background-color: #E92E2E\ +}\ +.ace-clouds-midnight .ace_fold {\ +background-color: #927C5D;\ +border-color: #929292\ +}\ +.ace-clouds-midnight .ace_storage,\ +.ace-clouds-midnight .ace_support.ace_class,\ +.ace-clouds-midnight .ace_support.ace_function,\ +.ace-clouds-midnight .ace_support.ace_other,\ +.ace-clouds-midnight .ace_support.ace_type {\ +color: #E92E2E\ +}\ +.ace-clouds-midnight .ace_string {\ +color: #5D90CD\ +}\ +.ace-clouds-midnight .ace_comment {\ +color: #3C403B\ +}\ +.ace-clouds-midnight .ace_entity.ace_name.ace_tag,\ +.ace-clouds-midnight .ace_entity.ace_other.ace_attribute-name {\ +color: #606060\ +}\ +.ace-clouds-midnight .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYHB3d/8PAAOIAdULw8qMAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-cobalt.js b/modules/backend/assets/vendor/ace/theme-cobalt.js new file mode 100755 index 0000000..c5b6f26 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-cobalt.js @@ -0,0 +1,113 @@ +ace.define("ace/theme/cobalt",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-cobalt"; +exports.cssText = ".ace-cobalt .ace_gutter {\ +background: #011e3a;\ +color: rgb(128,145,160)\ +}\ +.ace-cobalt .ace_print-margin {\ +width: 1px;\ +background: #555555\ +}\ +.ace-cobalt {\ +background-color: #002240;\ +color: #FFFFFF\ +}\ +.ace-cobalt .ace_cursor {\ +color: #FFFFFF\ +}\ +.ace-cobalt .ace_marker-layer .ace_selection {\ +background: rgba(179, 101, 57, 0.75)\ +}\ +.ace-cobalt.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #002240;\ +}\ +.ace-cobalt .ace_marker-layer .ace_step {\ +background: rgb(127, 111, 19)\ +}\ +.ace-cobalt .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgba(255, 255, 255, 0.15)\ +}\ +.ace-cobalt .ace_marker-layer .ace_active-line {\ +background: rgba(0, 0, 0, 0.35)\ +}\ +.ace-cobalt .ace_gutter-active-line {\ +background-color: rgba(0, 0, 0, 0.35)\ +}\ +.ace-cobalt .ace_marker-layer .ace_selected-word {\ +border: 1px solid rgba(179, 101, 57, 0.75)\ +}\ +.ace-cobalt .ace_invisible {\ +color: rgba(255, 255, 255, 0.15)\ +}\ +.ace-cobalt .ace_keyword,\ +.ace-cobalt .ace_meta {\ +color: #FF9D00\ +}\ +.ace-cobalt .ace_constant,\ +.ace-cobalt .ace_constant.ace_character,\ +.ace-cobalt .ace_constant.ace_character.ace_escape,\ +.ace-cobalt .ace_constant.ace_other {\ +color: #FF628C\ +}\ +.ace-cobalt .ace_invalid {\ +color: #F8F8F8;\ +background-color: #800F00\ +}\ +.ace-cobalt .ace_support {\ +color: #80FFBB\ +}\ +.ace-cobalt .ace_support.ace_constant {\ +color: #EB939A\ +}\ +.ace-cobalt .ace_fold {\ +background-color: #FF9D00;\ +border-color: #FFFFFF\ +}\ +.ace-cobalt .ace_support.ace_function {\ +color: #FFB054\ +}\ +.ace-cobalt .ace_storage {\ +color: #FFEE80\ +}\ +.ace-cobalt .ace_entity {\ +color: #FFDD00\ +}\ +.ace-cobalt .ace_string {\ +color: #3AD900\ +}\ +.ace-cobalt .ace_string.ace_regexp {\ +color: #80FFC2\ +}\ +.ace-cobalt .ace_comment {\ +font-style: italic;\ +color: #0088FF\ +}\ +.ace-cobalt .ace_heading,\ +.ace-cobalt .ace_markup.ace_heading {\ +color: #C8E4FD;\ +background-color: #001221\ +}\ +.ace-cobalt .ace_list,\ +.ace-cobalt .ace_markup.ace_list {\ +background-color: #130D26\ +}\ +.ace-cobalt .ace_variable {\ +color: #CCCCCC\ +}\ +.ace-cobalt .ace_variable.ace_language {\ +color: #FF80E1\ +}\ +.ace-cobalt .ace_meta.ace_tag {\ +color: #9EFFFF\ +}\ +.ace-cobalt .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYHCLSvkPAAP3AgSDTRd4AAAAAElFTkSuQmCC) right repeat-y\ +}\ +"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-crimson_editor.js b/modules/backend/assets/vendor/ace/theme-crimson_editor.js new file mode 100755 index 0000000..a188552 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-crimson_editor.js @@ -0,0 +1,118 @@ +ace.define("ace/theme/crimson_editor",["require","exports","module","ace/lib/dom"], function(require, exports, module) { +exports.isDark = false; +exports.cssText = ".ace-crimson-editor .ace_gutter {\ +background: #ebebeb;\ +color: #333;\ +overflow : hidden;\ +}\ +.ace-crimson-editor .ace_gutter-layer {\ +width: 100%;\ +text-align: right;\ +}\ +.ace-crimson-editor .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8;\ +}\ +.ace-crimson-editor {\ +background-color: #FFFFFF;\ +color: rgb(64, 64, 64);\ +}\ +.ace-crimson-editor .ace_cursor {\ +color: black;\ +}\ +.ace-crimson-editor .ace_invisible {\ +color: rgb(191, 191, 191);\ +}\ +.ace-crimson-editor .ace_identifier {\ +color: black;\ +}\ +.ace-crimson-editor .ace_keyword {\ +color: blue;\ +}\ +.ace-crimson-editor .ace_constant.ace_buildin {\ +color: rgb(88, 72, 246);\ +}\ +.ace-crimson-editor .ace_constant.ace_language {\ +color: rgb(255, 156, 0);\ +}\ +.ace-crimson-editor .ace_constant.ace_library {\ +color: rgb(6, 150, 14);\ +}\ +.ace-crimson-editor .ace_invalid {\ +text-decoration: line-through;\ +color: rgb(224, 0, 0);\ +}\ +.ace-crimson-editor .ace_fold {\ +}\ +.ace-crimson-editor .ace_support.ace_function {\ +color: rgb(192, 0, 0);\ +}\ +.ace-crimson-editor .ace_support.ace_constant {\ +color: rgb(6, 150, 14);\ +}\ +.ace-crimson-editor .ace_support.ace_type,\ +.ace-crimson-editor .ace_support.ace_class {\ +color: rgb(109, 121, 222);\ +}\ +.ace-crimson-editor .ace_keyword.ace_operator {\ +color: rgb(49, 132, 149);\ +}\ +.ace-crimson-editor .ace_string {\ +color: rgb(128, 0, 128);\ +}\ +.ace-crimson-editor .ace_comment {\ +color: rgb(76, 136, 107);\ +}\ +.ace-crimson-editor .ace_comment.ace_doc {\ +color: rgb(0, 102, 255);\ +}\ +.ace-crimson-editor .ace_comment.ace_doc.ace_tag {\ +color: rgb(128, 159, 191);\ +}\ +.ace-crimson-editor .ace_constant.ace_numeric {\ +color: rgb(0, 0, 64);\ +}\ +.ace-crimson-editor .ace_variable {\ +color: rgb(0, 64, 128);\ +}\ +.ace-crimson-editor .ace_xml-pe {\ +color: rgb(104, 104, 91);\ +}\ +.ace-crimson-editor .ace_marker-layer .ace_selection {\ +background: rgb(181, 213, 255);\ +}\ +.ace-crimson-editor .ace_marker-layer .ace_step {\ +background: rgb(252, 255, 0);\ +}\ +.ace-crimson-editor .ace_marker-layer .ace_stack {\ +background: rgb(164, 229, 101);\ +}\ +.ace-crimson-editor .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgb(192, 192, 192);\ +}\ +.ace-crimson-editor .ace_marker-layer .ace_active-line {\ +background: rgb(232, 242, 254);\ +}\ +.ace-crimson-editor .ace_gutter-active-line {\ +background-color : #dcdcdc;\ +}\ +.ace-crimson-editor .ace_meta.ace_tag {\ +color:rgb(28, 2, 255);\ +}\ +.ace-crimson-editor .ace_marker-layer .ace_selected-word {\ +background: rgb(250, 250, 255);\ +border: 1px solid rgb(200, 200, 250);\ +}\ +.ace-crimson-editor .ace_string.ace_regex {\ +color: rgb(192, 0, 192);\ +}\ +.ace-crimson-editor .ace_indent-guide {\ +background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\ +}"; + +exports.cssClass = "ace-crimson-editor"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-dawn.js b/modules/backend/assets/vendor/ace/theme-dawn.js new file mode 100755 index 0000000..f3c15c9 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-dawn.js @@ -0,0 +1,108 @@ +ace.define("ace/theme/dawn",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = false; +exports.cssClass = "ace-dawn"; +exports.cssText = ".ace-dawn .ace_gutter {\ +background: #ebebeb;\ +color: #333\ +}\ +.ace-dawn .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8\ +}\ +.ace-dawn {\ +background-color: #F9F9F9;\ +color: #080808\ +}\ +.ace-dawn .ace_cursor {\ +color: #000000\ +}\ +.ace-dawn .ace_marker-layer .ace_selection {\ +background: rgba(39, 95, 255, 0.30)\ +}\ +.ace-dawn.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #F9F9F9;\ +}\ +.ace-dawn .ace_marker-layer .ace_step {\ +background: rgb(255, 255, 0)\ +}\ +.ace-dawn .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgba(75, 75, 126, 0.50)\ +}\ +.ace-dawn .ace_marker-layer .ace_active-line {\ +background: rgba(36, 99, 180, 0.12)\ +}\ +.ace-dawn .ace_gutter-active-line {\ +background-color : #dcdcdc\ +}\ +.ace-dawn .ace_marker-layer .ace_selected-word {\ +border: 1px solid rgba(39, 95, 255, 0.30)\ +}\ +.ace-dawn .ace_invisible {\ +color: rgba(75, 75, 126, 0.50)\ +}\ +.ace-dawn .ace_keyword,\ +.ace-dawn .ace_meta {\ +color: #794938\ +}\ +.ace-dawn .ace_constant,\ +.ace-dawn .ace_constant.ace_character,\ +.ace-dawn .ace_constant.ace_character.ace_escape,\ +.ace-dawn .ace_constant.ace_other {\ +color: #811F24\ +}\ +.ace-dawn .ace_invalid.ace_illegal {\ +text-decoration: underline;\ +font-style: italic;\ +color: #F8F8F8;\ +background-color: #B52A1D\ +}\ +.ace-dawn .ace_invalid.ace_deprecated {\ +text-decoration: underline;\ +font-style: italic;\ +color: #B52A1D\ +}\ +.ace-dawn .ace_support {\ +color: #691C97\ +}\ +.ace-dawn .ace_support.ace_constant {\ +color: #B4371F\ +}\ +.ace-dawn .ace_fold {\ +background-color: #794938;\ +border-color: #080808\ +}\ +.ace-dawn .ace_list,\ +.ace-dawn .ace_markup.ace_list,\ +.ace-dawn .ace_support.ace_function {\ +color: #693A17\ +}\ +.ace-dawn .ace_storage {\ +font-style: italic;\ +color: #A71D5D\ +}\ +.ace-dawn .ace_string {\ +color: #0B6125\ +}\ +.ace-dawn .ace_string.ace_regexp {\ +color: #CF5628\ +}\ +.ace-dawn .ace_comment {\ +font-style: italic;\ +color: #5A525F\ +}\ +.ace-dawn .ace_heading,\ +.ace-dawn .ace_markup.ace_heading {\ +color: #19356D\ +}\ +.ace-dawn .ace_variable {\ +color: #234A97\ +}\ +.ace-dawn .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYLh/5+x/AAizA4hxNNsZAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-dreamweaver.js b/modules/backend/assets/vendor/ace/theme-dreamweaver.js new file mode 100755 index 0000000..632b1ea --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-dreamweaver.js @@ -0,0 +1,141 @@ +ace.define("ace/theme/dreamweaver",["require","exports","module","ace/lib/dom"], function(require, exports, module) { +exports.isDark = false; +exports.cssClass = "ace-dreamweaver"; +exports.cssText = ".ace-dreamweaver .ace_gutter {\ +background: #e8e8e8;\ +color: #333;\ +}\ +.ace-dreamweaver .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8;\ +}\ +.ace-dreamweaver {\ +background-color: #FFFFFF;\ +color: black;\ +}\ +.ace-dreamweaver .ace_fold {\ +background-color: #757AD8;\ +}\ +.ace-dreamweaver .ace_cursor {\ +color: black;\ +}\ +.ace-dreamweaver .ace_invisible {\ +color: rgb(191, 191, 191);\ +}\ +.ace-dreamweaver .ace_storage,\ +.ace-dreamweaver .ace_keyword {\ +color: blue;\ +}\ +.ace-dreamweaver .ace_constant.ace_buildin {\ +color: rgb(88, 72, 246);\ +}\ +.ace-dreamweaver .ace_constant.ace_language {\ +color: rgb(88, 92, 246);\ +}\ +.ace-dreamweaver .ace_constant.ace_library {\ +color: rgb(6, 150, 14);\ +}\ +.ace-dreamweaver .ace_invalid {\ +background-color: rgb(153, 0, 0);\ +color: white;\ +}\ +.ace-dreamweaver .ace_support.ace_function {\ +color: rgb(60, 76, 114);\ +}\ +.ace-dreamweaver .ace_support.ace_constant {\ +color: rgb(6, 150, 14);\ +}\ +.ace-dreamweaver .ace_support.ace_type,\ +.ace-dreamweaver .ace_support.ace_class {\ +color: #009;\ +}\ +.ace-dreamweaver .ace_support.ace_php_tag {\ +color: #f00;\ +}\ +.ace-dreamweaver .ace_keyword.ace_operator {\ +color: rgb(104, 118, 135);\ +}\ +.ace-dreamweaver .ace_string {\ +color: #00F;\ +}\ +.ace-dreamweaver .ace_comment {\ +color: rgb(76, 136, 107);\ +}\ +.ace-dreamweaver .ace_comment.ace_doc {\ +color: rgb(0, 102, 255);\ +}\ +.ace-dreamweaver .ace_comment.ace_doc.ace_tag {\ +color: rgb(128, 159, 191);\ +}\ +.ace-dreamweaver .ace_constant.ace_numeric {\ +color: rgb(0, 0, 205);\ +}\ +.ace-dreamweaver .ace_variable {\ +color: #06F\ +}\ +.ace-dreamweaver .ace_xml-pe {\ +color: rgb(104, 104, 91);\ +}\ +.ace-dreamweaver .ace_entity.ace_name.ace_function {\ +color: #00F;\ +}\ +.ace-dreamweaver .ace_heading {\ +color: rgb(12, 7, 255);\ +}\ +.ace-dreamweaver .ace_list {\ +color:rgb(185, 6, 144);\ +}\ +.ace-dreamweaver .ace_marker-layer .ace_selection {\ +background: rgb(181, 213, 255);\ +}\ +.ace-dreamweaver .ace_marker-layer .ace_step {\ +background: rgb(252, 255, 0);\ +}\ +.ace-dreamweaver .ace_marker-layer .ace_stack {\ +background: rgb(164, 229, 101);\ +}\ +.ace-dreamweaver .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgb(192, 192, 192);\ +}\ +.ace-dreamweaver .ace_marker-layer .ace_active-line {\ +background: rgba(0, 0, 0, 0.07);\ +}\ +.ace-dreamweaver .ace_gutter-active-line {\ +background-color : #DCDCDC;\ +}\ +.ace-dreamweaver .ace_marker-layer .ace_selected-word {\ +background: rgb(250, 250, 255);\ +border: 1px solid rgb(200, 200, 250);\ +}\ +.ace-dreamweaver .ace_meta.ace_tag {\ +color:#009;\ +}\ +.ace-dreamweaver .ace_meta.ace_tag.ace_anchor {\ +color:#060;\ +}\ +.ace-dreamweaver .ace_meta.ace_tag.ace_form {\ +color:#F90;\ +}\ +.ace-dreamweaver .ace_meta.ace_tag.ace_image {\ +color:#909;\ +}\ +.ace-dreamweaver .ace_meta.ace_tag.ace_script {\ +color:#900;\ +}\ +.ace-dreamweaver .ace_meta.ace_tag.ace_style {\ +color:#909;\ +}\ +.ace-dreamweaver .ace_meta.ace_tag.ace_table {\ +color:#099;\ +}\ +.ace-dreamweaver .ace_string.ace_regex {\ +color: rgb(255, 0, 0)\ +}\ +.ace-dreamweaver .ace_indent-guide {\ +background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-eclipse.js b/modules/backend/assets/vendor/ace/theme-eclipse.js new file mode 100755 index 0000000..63aa334 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-eclipse.js @@ -0,0 +1,98 @@ +ace.define("ace/theme/eclipse",["require","exports","module","ace/lib/dom"], function(require, exports, module) { +"use strict"; + +exports.isDark = false; +exports.cssText = ".ace-eclipse .ace_gutter {\ +background: #ebebeb;\ +border-right: 1px solid rgb(159, 159, 159);\ +color: rgb(136, 136, 136);\ +}\ +.ace-eclipse .ace_print-margin {\ +width: 1px;\ +background: #ebebeb;\ +}\ +.ace-eclipse {\ +background-color: #FFFFFF;\ +color: black;\ +}\ +.ace-eclipse .ace_fold {\ +background-color: rgb(60, 76, 114);\ +}\ +.ace-eclipse .ace_cursor {\ +color: black;\ +}\ +.ace-eclipse .ace_storage,\ +.ace-eclipse .ace_keyword,\ +.ace-eclipse .ace_variable {\ +color: rgb(127, 0, 85);\ +}\ +.ace-eclipse .ace_constant.ace_buildin {\ +color: rgb(88, 72, 246);\ +}\ +.ace-eclipse .ace_constant.ace_library {\ +color: rgb(6, 150, 14);\ +}\ +.ace-eclipse .ace_function {\ +color: rgb(60, 76, 114);\ +}\ +.ace-eclipse .ace_string {\ +color: rgb(42, 0, 255);\ +}\ +.ace-eclipse .ace_comment {\ +color: rgb(113, 150, 130);\ +}\ +.ace-eclipse .ace_comment.ace_doc {\ +color: rgb(63, 95, 191);\ +}\ +.ace-eclipse .ace_comment.ace_doc.ace_tag {\ +color: rgb(127, 159, 191);\ +}\ +.ace-eclipse .ace_constant.ace_numeric {\ +color: darkblue;\ +}\ +.ace-eclipse .ace_tag {\ +color: rgb(25, 118, 116);\ +}\ +.ace-eclipse .ace_type {\ +color: rgb(127, 0, 127);\ +}\ +.ace-eclipse .ace_xml-pe {\ +color: rgb(104, 104, 91);\ +}\ +.ace-eclipse .ace_marker-layer .ace_selection {\ +background: rgb(181, 213, 255);\ +}\ +.ace-eclipse .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgb(192, 192, 192);\ +}\ +.ace-eclipse .ace_meta.ace_tag {\ +color:rgb(25, 118, 116);\ +}\ +.ace-eclipse .ace_invisible {\ +color: #ddd;\ +}\ +.ace-eclipse .ace_entity.ace_other.ace_attribute-name {\ +color:rgb(127, 0, 127);\ +}\ +.ace-eclipse .ace_marker-layer .ace_step {\ +background: rgb(255, 255, 0);\ +}\ +.ace-eclipse .ace_active-line {\ +background: rgb(232, 242, 254);\ +}\ +.ace-eclipse .ace_gutter-active-line {\ +background-color : #DADADA;\ +}\ +.ace-eclipse .ace_marker-layer .ace_selected-word {\ +border: 1px solid rgb(181, 213, 255);\ +}\ +.ace-eclipse .ace_indent-guide {\ +background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\ +}"; + +exports.cssClass = "ace-eclipse"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-github.js b/modules/backend/assets/vendor/ace/theme-github.js new file mode 100755 index 0000000..d19512c --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-github.js @@ -0,0 +1,103 @@ +ace.define("ace/theme/github",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = false; +exports.cssClass = "ace-github"; +exports.cssText = "\ +.ace-github .ace_gutter {\ +background: #e8e8e8;\ +color: #AAA;\ +}\ +.ace-github {\ +background: #fff;\ +color: #000;\ +}\ +.ace-github .ace_keyword {\ +font-weight: bold;\ +}\ +.ace-github .ace_string {\ +color: #D14;\ +}\ +.ace-github .ace_variable.ace_class {\ +color: teal;\ +}\ +.ace-github .ace_constant.ace_numeric {\ +color: #099;\ +}\ +.ace-github .ace_constant.ace_buildin {\ +color: #0086B3;\ +}\ +.ace-github .ace_support.ace_function {\ +color: #0086B3;\ +}\ +.ace-github .ace_comment {\ +color: #998;\ +font-style: italic;\ +}\ +.ace-github .ace_variable.ace_language {\ +color: #0086B3;\ +}\ +.ace-github .ace_paren {\ +font-weight: bold;\ +}\ +.ace-github .ace_boolean {\ +font-weight: bold;\ +}\ +.ace-github .ace_string.ace_regexp {\ +color: #009926;\ +font-weight: normal;\ +}\ +.ace-github .ace_variable.ace_instance {\ +color: teal;\ +}\ +.ace-github .ace_constant.ace_language {\ +font-weight: bold;\ +}\ +.ace-github .ace_cursor {\ +color: black;\ +}\ +.ace-github.ace_focus .ace_marker-layer .ace_active-line {\ +background: rgb(255, 255, 204);\ +}\ +.ace-github .ace_marker-layer .ace_active-line {\ +background: rgb(245, 245, 245);\ +}\ +.ace-github .ace_marker-layer .ace_selection {\ +background: rgb(181, 213, 255);\ +}\ +.ace-github.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px white;\ +}\ +.ace-github.ace_nobold .ace_line > span {\ +font-weight: normal !important;\ +}\ +.ace-github .ace_marker-layer .ace_step {\ +background: rgb(252, 255, 0);\ +}\ +.ace-github .ace_marker-layer .ace_stack {\ +background: rgb(164, 229, 101);\ +}\ +.ace-github .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgb(192, 192, 192);\ +}\ +.ace-github .ace_gutter-active-line {\ +background-color : rgba(0, 0, 0, 0.07);\ +}\ +.ace-github .ace_marker-layer .ace_selected-word {\ +background: rgb(250, 250, 255);\ +border: 1px solid rgb(200, 200, 250);\ +}\ +.ace-github .ace_invisible {\ +color: #BFBFBF\ +}\ +.ace-github .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8;\ +}\ +.ace-github .ace_indent-guide {\ +background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\ +}"; + + var dom = require("../lib/dom"); + dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-idle_fingers.js b/modules/backend/assets/vendor/ace/theme-idle_fingers.js new file mode 100755 index 0000000..7fcf1cb --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-idle_fingers.js @@ -0,0 +1,96 @@ +ace.define("ace/theme/idle_fingers",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-idle-fingers"; +exports.cssText = ".ace-idle-fingers .ace_gutter {\ +background: #3b3b3b;\ +color: rgb(153,153,153)\ +}\ +.ace-idle-fingers .ace_print-margin {\ +width: 1px;\ +background: #3b3b3b\ +}\ +.ace-idle-fingers {\ +background-color: #323232;\ +color: #FFFFFF\ +}\ +.ace-idle-fingers .ace_cursor {\ +color: #91FF00\ +}\ +.ace-idle-fingers .ace_marker-layer .ace_selection {\ +background: rgba(90, 100, 126, 0.88)\ +}\ +.ace-idle-fingers.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #323232;\ +}\ +.ace-idle-fingers .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-idle-fingers .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #404040\ +}\ +.ace-idle-fingers .ace_marker-layer .ace_active-line {\ +background: #353637\ +}\ +.ace-idle-fingers .ace_gutter-active-line {\ +background-color: #353637\ +}\ +.ace-idle-fingers .ace_marker-layer .ace_selected-word {\ +border: 1px solid rgba(90, 100, 126, 0.88)\ +}\ +.ace-idle-fingers .ace_invisible {\ +color: #404040\ +}\ +.ace-idle-fingers .ace_keyword,\ +.ace-idle-fingers .ace_meta {\ +color: #CC7833\ +}\ +.ace-idle-fingers .ace_constant,\ +.ace-idle-fingers .ace_constant.ace_character,\ +.ace-idle-fingers .ace_constant.ace_character.ace_escape,\ +.ace-idle-fingers .ace_constant.ace_other,\ +.ace-idle-fingers .ace_support.ace_constant {\ +color: #6C99BB\ +}\ +.ace-idle-fingers .ace_invalid {\ +color: #FFFFFF;\ +background-color: #FF0000\ +}\ +.ace-idle-fingers .ace_fold {\ +background-color: #CC7833;\ +border-color: #FFFFFF\ +}\ +.ace-idle-fingers .ace_support.ace_function {\ +color: #B83426\ +}\ +.ace-idle-fingers .ace_variable.ace_parameter {\ +font-style: italic\ +}\ +.ace-idle-fingers .ace_string {\ +color: #A5C261\ +}\ +.ace-idle-fingers .ace_string.ace_regexp {\ +color: #CCCC33\ +}\ +.ace-idle-fingers .ace_comment {\ +font-style: italic;\ +color: #BC9458\ +}\ +.ace-idle-fingers .ace_meta.ace_tag {\ +color: #FFE5BB\ +}\ +.ace-idle-fingers .ace_entity.ace_name {\ +color: #FFC66D\ +}\ +.ace-idle-fingers .ace_collab.ace_user1 {\ +color: #323232;\ +background-color: #FFF980\ +}\ +.ace-idle-fingers .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWMwMjLyZYiPj/8PAAreAwAI1+g0AAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-iplastic.js b/modules/backend/assets/vendor/ace/theme-iplastic.js new file mode 100755 index 0000000..593aa00 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-iplastic.js @@ -0,0 +1,121 @@ +ace.define("ace/theme/iplastic",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = false; +exports.cssClass = "ace-iplastic"; +exports.cssText = ".ace-iplastic .ace_gutter {\ +background: #dddddd;\ +color: #666666\ +}\ +.ace-iplastic .ace_print-margin {\ +width: 1px;\ +background: #bbbbbb\ +}\ +.ace-iplastic {\ +background-color: #eeeeee;\ +color: #333333\ +}\ +.ace-iplastic .ace_cursor {\ +color: #333\ +}\ +.ace-iplastic .ace_marker-layer .ace_selection {\ +background: #BAD6FD;\ +}\ +.ace-iplastic.ace_multiselect .ace_selection.ace_start {\ +border-radius: 4px\ +}\ +.ace-iplastic .ace_marker-layer .ace_step {\ +background: #444444\ +}\ +.ace-iplastic .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #49483E;\ +background: #FFF799\ +}\ +.ace-iplastic .ace_marker-layer .ace_active-line {\ +background: #e5e5e5\ +}\ +.ace-iplastic .ace_gutter-active-line {\ +background-color: #eeeeee\ +}\ +.ace-iplastic .ace_marker-layer .ace_selected-word {\ +border: 1px solid #555555;\ +border-radius:4px\ +}\ +.ace-iplastic .ace_invisible {\ +color: #999999\ +}\ +.ace-iplastic .ace_entity.ace_name.ace_tag,\ +.ace-iplastic .ace_keyword,\ +.ace-iplastic .ace_meta.ace_tag,\ +.ace-iplastic .ace_storage {\ +color: #0000FF\ +}\ +.ace-iplastic .ace_punctuation,\ +.ace-iplastic .ace_punctuation.ace_tag {\ +color: #000\ +}\ +.ace-iplastic .ace_constant {\ +color: #333333;\ +font-weight: 700\ +}\ +.ace-iplastic .ace_constant.ace_character,\ +.ace-iplastic .ace_constant.ace_language,\ +.ace-iplastic .ace_constant.ace_numeric,\ +.ace-iplastic .ace_constant.ace_other {\ +color: #0066FF;\ +font-weight: 700\ +}\ +.ace-iplastic .ace_constant.ace_numeric{\ +font-weight: 100\ +}\ +.ace-iplastic .ace_invalid {\ +color: #F8F8F0;\ +background-color: #F92672\ +}\ +.ace-iplastic .ace_invalid.ace_deprecated {\ +color: #F8F8F0;\ +background-color: #AE81FF\ +}\ +.ace-iplastic .ace_support.ace_constant,\ +.ace-iplastic .ace_support.ace_function {\ +color: #333333;\ +font-weight: 700\ +}\ +.ace-iplastic .ace_fold {\ +background-color: #464646;\ +border-color: #F8F8F2\ +}\ +.ace-iplastic .ace_storage.ace_type,\ +.ace-iplastic .ace_support.ace_class,\ +.ace-iplastic .ace_support.ace_type {\ +color: #3333fc;\ +font-weight: 700\ +}\ +.ace-iplastic .ace_entity.ace_name.ace_function,\ +.ace-iplastic .ace_entity.ace_other,\ +.ace-iplastic .ace_entity.ace_other.ace_attribute-name,\ +.ace-iplastic .ace_variable {\ +color: #3366cc;\ +font-style: italic\ +}\ +.ace-iplastic .ace_variable.ace_parameter {\ +font-style: italic;\ +color: #2469E0\ +}\ +.ace-iplastic .ace_string {\ +color: #a55f03\ +}\ +.ace-iplastic .ace_comment {\ +color: #777777;\ +font-style: italic\ +}\ +.ace-iplastic .ace_fold-widget {\ +background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAANElEQVR42mWKsQ0AMAzC8ixLlrzQjzmBiEjp0A6WwBCSPgKAXoLkqSot7nN3yMwR7pZ32NzpKkVoDBUxKAAAAABJRU5ErkJggg==);\ +}\ +.ace-iplastic .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAABlJREFUeNpi+P//PwMzMzPzfwAAAAD//wMAGRsECSML/RIAAAAASUVORK5CYII=) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-katzenmilch.js b/modules/backend/assets/vendor/ace/theme-katzenmilch.js new file mode 100755 index 0000000..f65ce4a --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-katzenmilch.js @@ -0,0 +1,121 @@ +ace.define("ace/theme/katzenmilch",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = false; +exports.cssClass = "ace-katzenmilch"; +exports.cssText = ".ace-katzenmilch .ace_gutter,\ +.ace-katzenmilch .ace_gutter {\ +background: #e8e8e8;\ +color: #333\ +}\ +.ace-katzenmilch .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8\ +}\ +.ace-katzenmilch {\ +background-color: #f3f2f3;\ +color: rgba(15, 0, 9, 1.0)\ +}\ +.ace-katzenmilch .ace_cursor {\ +border-left: 2px solid #100011\ +}\ +.ace-katzenmilch .ace_overwrite-cursors .ace_cursor {\ +border-left: 0px;\ +border-bottom: 1px solid #100011\ +}\ +.ace-katzenmilch .ace_marker-layer .ace_selection {\ +background: rgba(100, 5, 208, 0.27)\ +}\ +.ace-katzenmilch.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #f3f2f3;\ +}\ +.ace-katzenmilch .ace_marker-layer .ace_step {\ +background: rgb(198, 219, 174)\ +}\ +.ace-katzenmilch .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgba(0, 0, 0, 0.33);\ +}\ +.ace-katzenmilch .ace_marker-layer .ace_active-line {\ +background: rgb(232, 242, 254)\ +}\ +.ace-katzenmilch .ace_gutter-active-line {\ +background-color: rgb(232, 242, 254)\ +}\ +.ace-katzenmilch .ace_marker-layer .ace_selected-word {\ +border: 1px solid rgba(100, 5, 208, 0.27)\ +}\ +.ace-katzenmilch .ace_invisible {\ +color: #BFBFBF\ +}\ +.ace-katzenmilch .ace_fold {\ +background-color: rgba(2, 95, 73, 0.97);\ +border-color: rgba(15, 0, 9, 1.0)\ +}\ +.ace-katzenmilch .ace_keyword {\ +color: #674Aa8;\ +rbackground-color: rgba(163, 170, 216, 0.055)\ +}\ +.ace-katzenmilch .ace_constant.ace_language {\ +color: #7D7e52;\ +rbackground-color: rgba(189, 190, 130, 0.059)\ +}\ +.ace-katzenmilch .ace_constant.ace_numeric {\ +color: rgba(79, 130, 123, 0.93);\ +rbackground-color: rgba(119, 194, 187, 0.059)\ +}\ +.ace-katzenmilch .ace_constant.ace_character,\ +.ace-katzenmilch .ace_constant.ace_other {\ +color: rgba(2, 95, 105, 1.0);\ +rbackground-color: rgba(127, 34, 153, 0.063)\ +}\ +.ace-katzenmilch .ace_support.ace_function {\ +color: #9D7e62;\ +rbackground-color: rgba(189, 190, 130, 0.039)\ +}\ +.ace-katzenmilch .ace_support.ace_class {\ +color: rgba(239, 106, 167, 1.0);\ +rbackground-color: rgba(239, 106, 167, 0.063)\ +}\ +.ace-katzenmilch .ace_storage {\ +color: rgba(123, 92, 191, 1.0);\ +rbackground-color: rgba(139, 93, 223, 0.051)\ +}\ +.ace-katzenmilch .ace_invalid {\ +color: #DFDFD5;\ +rbackground-color: #CC1B27\ +}\ +.ace-katzenmilch .ace_string {\ +color: #5a5f9b;\ +rbackground-color: rgba(170, 175, 219, 0.035)\ +}\ +.ace-katzenmilch .ace_comment {\ +font-style: italic;\ +color: rgba(64, 79, 80, 0.67);\ +rbackground-color: rgba(95, 15, 255, 0.0078)\ +}\ +.ace-katzenmilch .ace_entity.ace_name.ace_function,\ +.ace-katzenmilch .ace_variable {\ +color: rgba(2, 95, 73, 0.97);\ +rbackground-color: rgba(34, 255, 73, 0.12)\ +}\ +.ace-katzenmilch .ace_variable.ace_language {\ +color: #316fcf;\ +rbackground-color: rgba(58, 175, 255, 0.039)\ +}\ +.ace-katzenmilch .ace_variable.ace_parameter {\ +font-style: italic;\ +color: rgba(51, 150, 159, 0.87);\ +rbackground-color: rgba(5, 214, 249, 0.043)\ +}\ +.ace-katzenmilch .ace_entity.ace_other.ace_attribute-name {\ +color: rgba(73, 70, 194, 0.93);\ +rbackground-color: rgba(73, 134, 194, 0.035)\ +}\ +.ace-katzenmilch .ace_entity.ace_name.ace_tag {\ +color: #3976a2;\ +rbackground-color: rgba(73, 166, 210, 0.039)\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-kr_theme.js b/modules/backend/assets/vendor/ace/theme-kr_theme.js new file mode 100755 index 0000000..8818b33 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-kr_theme.js @@ -0,0 +1,104 @@ +ace.define("ace/theme/kr_theme",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-kr-theme"; +exports.cssText = ".ace-kr-theme .ace_gutter {\ +background: #1c1917;\ +color: #FCFFE0\ +}\ +.ace-kr-theme .ace_print-margin {\ +width: 1px;\ +background: #1c1917\ +}\ +.ace-kr-theme {\ +background-color: #0B0A09;\ +color: #FCFFE0\ +}\ +.ace-kr-theme .ace_cursor {\ +color: #FF9900\ +}\ +.ace-kr-theme .ace_marker-layer .ace_selection {\ +background: rgba(170, 0, 255, 0.45)\ +}\ +.ace-kr-theme.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #0B0A09;\ +}\ +.ace-kr-theme .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-kr-theme .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgba(255, 177, 111, 0.32)\ +}\ +.ace-kr-theme .ace_marker-layer .ace_active-line {\ +background: #38403D\ +}\ +.ace-kr-theme .ace_gutter-active-line {\ +background-color : #38403D\ +}\ +.ace-kr-theme .ace_marker-layer .ace_selected-word {\ +border: 1px solid rgba(170, 0, 255, 0.45)\ +}\ +.ace-kr-theme .ace_invisible {\ +color: rgba(255, 177, 111, 0.32)\ +}\ +.ace-kr-theme .ace_keyword,\ +.ace-kr-theme .ace_meta {\ +color: #949C8B\ +}\ +.ace-kr-theme .ace_constant,\ +.ace-kr-theme .ace_constant.ace_character,\ +.ace-kr-theme .ace_constant.ace_character.ace_escape,\ +.ace-kr-theme .ace_constant.ace_other {\ +color: rgba(210, 117, 24, 0.76)\ +}\ +.ace-kr-theme .ace_invalid {\ +color: #F8F8F8;\ +background-color: #A41300\ +}\ +.ace-kr-theme .ace_support {\ +color: #9FC28A\ +}\ +.ace-kr-theme .ace_support.ace_constant {\ +color: #C27E66\ +}\ +.ace-kr-theme .ace_fold {\ +background-color: #949C8B;\ +border-color: #FCFFE0\ +}\ +.ace-kr-theme .ace_support.ace_function {\ +color: #85873A\ +}\ +.ace-kr-theme .ace_storage {\ +color: #FFEE80\ +}\ +.ace-kr-theme .ace_string {\ +color: rgba(164, 161, 181, 0.8)\ +}\ +.ace-kr-theme .ace_string.ace_regexp {\ +color: rgba(125, 255, 192, 0.65)\ +}\ +.ace-kr-theme .ace_comment {\ +font-style: italic;\ +color: #706D5B\ +}\ +.ace-kr-theme .ace_variable {\ +color: #D1A796\ +}\ +.ace-kr-theme .ace_list,\ +.ace-kr-theme .ace_markup.ace_list {\ +background-color: #0F0040\ +}\ +.ace-kr-theme .ace_variable.ace_language {\ +color: #FF80E1\ +}\ +.ace-kr-theme .ace_meta.ace_tag {\ +color: #BABD9C\ +}\ +.ace-kr-theme .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYFBXV/8PAAJoAXX4kT2EAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-kuroir.js b/modules/backend/assets/vendor/ace/theme-kuroir.js new file mode 100755 index 0000000..30e0a8b --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-kuroir.js @@ -0,0 +1,61 @@ +ace.define("ace/theme/kuroir",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = false; +exports.cssClass = "ace-kuroir"; +exports.cssText = "\ +.ace-kuroir .ace_gutter {\ +background: #e8e8e8;\ +color: #333;\ +}\ +.ace-kuroir .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8;\ +}\ +.ace-kuroir {\ +background-color: #E8E9E8;\ +color: #363636;\ +}\ +.ace-kuroir .ace_cursor {\ +color: #202020;\ +}\ +.ace-kuroir .ace_marker-layer .ace_selection {\ +background: rgba(245, 170, 0, 0.57);\ +}\ +.ace-kuroir.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #E8E9E8;\ +}\ +.ace-kuroir .ace_marker-layer .ace_step {\ +background: rgb(198, 219, 174);\ +}\ +.ace-kuroir .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgba(0, 0, 0, 0.29);\ +}\ +.ace-kuroir .ace_marker-layer .ace_active-line {\ +background: rgba(203, 220, 47, 0.22);\ +}\ +.ace-kuroir .ace_gutter-active-line {\ +background-color: rgba(203, 220, 47, 0.22);\ +}\ +.ace-kuroir .ace_marker-layer .ace_selected-word {\ +border: 1px solid rgba(245, 170, 0, 0.57);\ +}\ +.ace-kuroir .ace_invisible {\ +color: #BFBFBF\ +}\ +.ace-kuroir .ace_fold {\ +border-color: #363636;\ +}\ +.ace-kuroir .ace_constant{color:#CD6839;}.ace-kuroir .ace_constant.ace_numeric{color:#9A5925;}.ace-kuroir .ace_support{color:#104E8B;}.ace-kuroir .ace_support.ace_function{color:#005273;}.ace-kuroir .ace_support.ace_constant{color:#CF6A4C;}.ace-kuroir .ace_storage{color:#A52A2A;}.ace-kuroir .ace_invalid.ace_illegal{color:#FD1224;\ +background-color:rgba(255, 6, 0, 0.15);}.ace-kuroir .ace_invalid.ace_deprecated{text-decoration:underline;\ +font-style:italic;\ +color:#FD1732;\ +background-color:#E8E9E8;}.ace-kuroir .ace_string{color:#639300;}.ace-kuroir .ace_string.ace_regexp{color:#417E00;\ +background-color:#C9D4BE;}.ace-kuroir .ace_comment{color:rgba(148, 148, 148, 0.91);\ +background-color:rgba(220, 220, 220, 0.56);}.ace-kuroir .ace_variable{color:#009ACD;}.ace-kuroir .ace_meta.ace_tag{color:#005273;}.ace-kuroir .ace_markup.ace_heading{color:#B8012D;\ +background-color:rgba(191, 97, 51, 0.051);}.ace-kuroir .ace_markup.ace_list{color:#8F5B26;}\ +"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-merbivore.js b/modules/backend/assets/vendor/ace/theme-merbivore.js new file mode 100755 index 0000000..fc0a72f --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-merbivore.js @@ -0,0 +1,95 @@ +ace.define("ace/theme/merbivore",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-merbivore"; +exports.cssText = ".ace-merbivore .ace_gutter {\ +background: #202020;\ +color: #E6E1DC\ +}\ +.ace-merbivore .ace_print-margin {\ +width: 1px;\ +background: #555651\ +}\ +.ace-merbivore {\ +background-color: #161616;\ +color: #E6E1DC\ +}\ +.ace-merbivore .ace_cursor {\ +color: #FFFFFF\ +}\ +.ace-merbivore .ace_marker-layer .ace_selection {\ +background: #454545\ +}\ +.ace-merbivore.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #161616;\ +}\ +.ace-merbivore .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-merbivore .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #404040\ +}\ +.ace-merbivore .ace_marker-layer .ace_active-line {\ +background: #333435\ +}\ +.ace-merbivore .ace_gutter-active-line {\ +background-color: #333435\ +}\ +.ace-merbivore .ace_marker-layer .ace_selected-word {\ +border: 1px solid #454545\ +}\ +.ace-merbivore .ace_invisible {\ +color: #404040\ +}\ +.ace-merbivore .ace_entity.ace_name.ace_tag,\ +.ace-merbivore .ace_keyword,\ +.ace-merbivore .ace_meta,\ +.ace-merbivore .ace_meta.ace_tag,\ +.ace-merbivore .ace_storage,\ +.ace-merbivore .ace_support.ace_function {\ +color: #FC6F09\ +}\ +.ace-merbivore .ace_constant,\ +.ace-merbivore .ace_constant.ace_character,\ +.ace-merbivore .ace_constant.ace_character.ace_escape,\ +.ace-merbivore .ace_constant.ace_other,\ +.ace-merbivore .ace_support.ace_type {\ +color: #1EDAFB\ +}\ +.ace-merbivore .ace_constant.ace_character.ace_escape {\ +color: #519F50\ +}\ +.ace-merbivore .ace_constant.ace_language {\ +color: #FDC251\ +}\ +.ace-merbivore .ace_constant.ace_library,\ +.ace-merbivore .ace_string,\ +.ace-merbivore .ace_support.ace_constant {\ +color: #8DFF0A\ +}\ +.ace-merbivore .ace_constant.ace_numeric {\ +color: #58C554\ +}\ +.ace-merbivore .ace_invalid {\ +color: #FFFFFF;\ +background-color: #990000\ +}\ +.ace-merbivore .ace_fold {\ +background-color: #FC6F09;\ +border-color: #E6E1DC\ +}\ +.ace-merbivore .ace_comment {\ +font-style: italic;\ +color: #AD2EA4\ +}\ +.ace-merbivore .ace_entity.ace_other.ace_attribute-name {\ +color: #FFFF89\ +}\ +.ace-merbivore .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWMQFxf3ZXB1df0PAAdsAmERTkEHAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-merbivore_soft.js b/modules/backend/assets/vendor/ace/theme-merbivore_soft.js new file mode 100755 index 0000000..eff2464 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-merbivore_soft.js @@ -0,0 +1,96 @@ +ace.define("ace/theme/merbivore_soft",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-merbivore-soft"; +exports.cssText = ".ace-merbivore-soft .ace_gutter {\ +background: #262424;\ +color: #E6E1DC\ +}\ +.ace-merbivore-soft .ace_print-margin {\ +width: 1px;\ +background: #262424\ +}\ +.ace-merbivore-soft {\ +background-color: #1C1C1C;\ +color: #E6E1DC\ +}\ +.ace-merbivore-soft .ace_cursor {\ +color: #FFFFFF\ +}\ +.ace-merbivore-soft .ace_marker-layer .ace_selection {\ +background: #494949\ +}\ +.ace-merbivore-soft.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #1C1C1C;\ +}\ +.ace-merbivore-soft .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-merbivore-soft .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #404040\ +}\ +.ace-merbivore-soft .ace_marker-layer .ace_active-line {\ +background: #333435\ +}\ +.ace-merbivore-soft .ace_gutter-active-line {\ +background-color: #333435\ +}\ +.ace-merbivore-soft .ace_marker-layer .ace_selected-word {\ +border: 1px solid #494949\ +}\ +.ace-merbivore-soft .ace_invisible {\ +color: #404040\ +}\ +.ace-merbivore-soft .ace_entity.ace_name.ace_tag,\ +.ace-merbivore-soft .ace_keyword,\ +.ace-merbivore-soft .ace_meta,\ +.ace-merbivore-soft .ace_meta.ace_tag,\ +.ace-merbivore-soft .ace_storage {\ +color: #FC803A\ +}\ +.ace-merbivore-soft .ace_constant,\ +.ace-merbivore-soft .ace_constant.ace_character,\ +.ace-merbivore-soft .ace_constant.ace_character.ace_escape,\ +.ace-merbivore-soft .ace_constant.ace_other,\ +.ace-merbivore-soft .ace_support.ace_type {\ +color: #68C1D8\ +}\ +.ace-merbivore-soft .ace_constant.ace_character.ace_escape {\ +color: #B3E5B4\ +}\ +.ace-merbivore-soft .ace_constant.ace_language {\ +color: #E1C582\ +}\ +.ace-merbivore-soft .ace_constant.ace_library,\ +.ace-merbivore-soft .ace_string,\ +.ace-merbivore-soft .ace_support.ace_constant {\ +color: #8EC65F\ +}\ +.ace-merbivore-soft .ace_constant.ace_numeric {\ +color: #7FC578\ +}\ +.ace-merbivore-soft .ace_invalid,\ +.ace-merbivore-soft .ace_invalid.ace_deprecated {\ +color: #FFFFFF;\ +background-color: #FE3838\ +}\ +.ace-merbivore-soft .ace_fold {\ +background-color: #FC803A;\ +border-color: #E6E1DC\ +}\ +.ace-merbivore-soft .ace_comment,\ +.ace-merbivore-soft .ace_meta {\ +font-style: italic;\ +color: #AC4BB8\ +}\ +.ace-merbivore-soft .ace_entity.ace_other.ace_attribute-name {\ +color: #EAF1A3\ +}\ +.ace-merbivore-soft .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWOQkpLyZfD09PwPAAfYAnaStpHRAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-mono_industrial.js b/modules/backend/assets/vendor/ace/theme-mono_industrial.js new file mode 100755 index 0000000..0ece030 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-mono_industrial.js @@ -0,0 +1,107 @@ +ace.define("ace/theme/mono_industrial",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-mono-industrial"; +exports.cssText = ".ace-mono-industrial .ace_gutter {\ +background: #1d2521;\ +color: #C5C9C9\ +}\ +.ace-mono-industrial .ace_print-margin {\ +width: 1px;\ +background: #555651\ +}\ +.ace-mono-industrial {\ +background-color: #222C28;\ +color: #FFFFFF\ +}\ +.ace-mono-industrial .ace_cursor {\ +color: #FFFFFF\ +}\ +.ace-mono-industrial .ace_marker-layer .ace_selection {\ +background: rgba(145, 153, 148, 0.40)\ +}\ +.ace-mono-industrial.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #222C28;\ +}\ +.ace-mono-industrial .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-mono-industrial .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgba(102, 108, 104, 0.50)\ +}\ +.ace-mono-industrial .ace_marker-layer .ace_active-line {\ +background: rgba(12, 13, 12, 0.25)\ +}\ +.ace-mono-industrial .ace_gutter-active-line {\ +background-color: rgba(12, 13, 12, 0.25)\ +}\ +.ace-mono-industrial .ace_marker-layer .ace_selected-word {\ +border: 1px solid rgba(145, 153, 148, 0.40)\ +}\ +.ace-mono-industrial .ace_invisible {\ +color: rgba(102, 108, 104, 0.50)\ +}\ +.ace-mono-industrial .ace_string {\ +background-color: #151C19;\ +color: #FFFFFF\ +}\ +.ace-mono-industrial .ace_keyword,\ +.ace-mono-industrial .ace_meta {\ +color: #A39E64\ +}\ +.ace-mono-industrial .ace_constant,\ +.ace-mono-industrial .ace_constant.ace_character,\ +.ace-mono-industrial .ace_constant.ace_character.ace_escape,\ +.ace-mono-industrial .ace_constant.ace_numeric,\ +.ace-mono-industrial .ace_constant.ace_other {\ +color: #E98800\ +}\ +.ace-mono-industrial .ace_entity.ace_name.ace_function,\ +.ace-mono-industrial .ace_keyword.ace_operator,\ +.ace-mono-industrial .ace_variable {\ +color: #A8B3AB\ +}\ +.ace-mono-industrial .ace_invalid {\ +color: #FFFFFF;\ +background-color: rgba(153, 0, 0, 0.68)\ +}\ +.ace-mono-industrial .ace_support.ace_constant {\ +color: #C87500\ +}\ +.ace-mono-industrial .ace_fold {\ +background-color: #A8B3AB;\ +border-color: #FFFFFF\ +}\ +.ace-mono-industrial .ace_support.ace_function {\ +color: #588E60\ +}\ +.ace-mono-industrial .ace_entity.ace_name,\ +.ace-mono-industrial .ace_support.ace_class,\ +.ace-mono-industrial .ace_support.ace_type {\ +color: #5778B6\ +}\ +.ace-mono-industrial .ace_storage {\ +color: #C23B00\ +}\ +.ace-mono-industrial .ace_variable.ace_language,\ +.ace-mono-industrial .ace_variable.ace_parameter {\ +color: #648BD2\ +}\ +.ace-mono-industrial .ace_comment {\ +color: #666C68;\ +background-color: #151C19\ +}\ +.ace-mono-industrial .ace_entity.ace_other.ace_attribute-name {\ +color: #909993\ +}\ +.ace-mono-industrial .ace_entity.ace_name.ace_tag {\ +color: #A65EFF\ +}\ +.ace-mono-industrial .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNQ1NbwZfALD/4PAAlTArlEC4r/AAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-monokai.js b/modules/backend/assets/vendor/ace/theme-monokai.js new file mode 100755 index 0000000..322c2fa --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-monokai.js @@ -0,0 +1,105 @@ +ace.define("ace/theme/monokai",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-monokai"; +exports.cssText = ".ace-monokai .ace_gutter {\ +background: #2F3129;\ +color: #8F908A\ +}\ +.ace-monokai .ace_print-margin {\ +width: 1px;\ +background: #555651\ +}\ +.ace-monokai {\ +background-color: #272822;\ +color: #F8F8F2\ +}\ +.ace-monokai .ace_cursor {\ +color: #F8F8F0\ +}\ +.ace-monokai .ace_marker-layer .ace_selection {\ +background: #49483E\ +}\ +.ace-monokai.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #272822;\ +}\ +.ace-monokai .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-monokai .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #49483E\ +}\ +.ace-monokai .ace_marker-layer .ace_active-line {\ +background: #202020\ +}\ +.ace-monokai .ace_gutter-active-line {\ +background-color: #272727\ +}\ +.ace-monokai .ace_marker-layer .ace_selected-word {\ +border: 1px solid #49483E\ +}\ +.ace-monokai .ace_invisible {\ +color: #52524d\ +}\ +.ace-monokai .ace_entity.ace_name.ace_tag,\ +.ace-monokai .ace_keyword,\ +.ace-monokai .ace_meta.ace_tag,\ +.ace-monokai .ace_storage {\ +color: #F92672\ +}\ +.ace-monokai .ace_punctuation,\ +.ace-monokai .ace_punctuation.ace_tag {\ +color: #fff\ +}\ +.ace-monokai .ace_constant.ace_character,\ +.ace-monokai .ace_constant.ace_language,\ +.ace-monokai .ace_constant.ace_numeric,\ +.ace-monokai .ace_constant.ace_other {\ +color: #AE81FF\ +}\ +.ace-monokai .ace_invalid {\ +color: #F8F8F0;\ +background-color: #F92672\ +}\ +.ace-monokai .ace_invalid.ace_deprecated {\ +color: #F8F8F0;\ +background-color: #AE81FF\ +}\ +.ace-monokai .ace_support.ace_constant,\ +.ace-monokai .ace_support.ace_function {\ +color: #66D9EF\ +}\ +.ace-monokai .ace_fold {\ +background-color: #A6E22E;\ +border-color: #F8F8F2\ +}\ +.ace-monokai .ace_storage.ace_type,\ +.ace-monokai .ace_support.ace_class,\ +.ace-monokai .ace_support.ace_type {\ +font-style: italic;\ +color: #66D9EF\ +}\ +.ace-monokai .ace_entity.ace_name.ace_function,\ +.ace-monokai .ace_entity.ace_other,\ +.ace-monokai .ace_entity.ace_other.ace_attribute-name,\ +.ace-monokai .ace_variable {\ +color: #A6E22E\ +}\ +.ace-monokai .ace_variable.ace_parameter {\ +font-style: italic;\ +color: #FD971F\ +}\ +.ace-monokai .ace_string {\ +color: #E6DB74\ +}\ +.ace-monokai .ace_comment {\ +color: #75715E\ +}\ +.ace-monokai .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ0FD0ZXBzd/wPAAjVAoxeSgNeAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-pastel_on_dark.js b/modules/backend/assets/vendor/ace/theme-pastel_on_dark.js new file mode 100755 index 0000000..2631ae0 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-pastel_on_dark.js @@ -0,0 +1,108 @@ +ace.define("ace/theme/pastel_on_dark",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-pastel-on-dark"; +exports.cssText = ".ace-pastel-on-dark .ace_gutter {\ +background: #353030;\ +color: #8F938F\ +}\ +.ace-pastel-on-dark .ace_print-margin {\ +width: 1px;\ +background: #353030\ +}\ +.ace-pastel-on-dark {\ +background-color: #2C2828;\ +color: #8F938F\ +}\ +.ace-pastel-on-dark .ace_cursor {\ +color: #A7A7A7\ +}\ +.ace-pastel-on-dark .ace_marker-layer .ace_selection {\ +background: rgba(221, 240, 255, 0.20)\ +}\ +.ace-pastel-on-dark.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #2C2828;\ +}\ +.ace-pastel-on-dark .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-pastel-on-dark .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgba(255, 255, 255, 0.25)\ +}\ +.ace-pastel-on-dark .ace_marker-layer .ace_active-line {\ +background: rgba(255, 255, 255, 0.031)\ +}\ +.ace-pastel-on-dark .ace_gutter-active-line {\ +background-color: rgba(255, 255, 255, 0.031)\ +}\ +.ace-pastel-on-dark .ace_marker-layer .ace_selected-word {\ +border: 1px solid rgba(221, 240, 255, 0.20)\ +}\ +.ace-pastel-on-dark .ace_invisible {\ +color: rgba(255, 255, 255, 0.25)\ +}\ +.ace-pastel-on-dark .ace_keyword,\ +.ace-pastel-on-dark .ace_meta {\ +color: #757aD8\ +}\ +.ace-pastel-on-dark .ace_constant,\ +.ace-pastel-on-dark .ace_constant.ace_character,\ +.ace-pastel-on-dark .ace_constant.ace_character.ace_escape,\ +.ace-pastel-on-dark .ace_constant.ace_other {\ +color: #4FB7C5\ +}\ +.ace-pastel-on-dark .ace_keyword.ace_operator {\ +color: #797878\ +}\ +.ace-pastel-on-dark .ace_constant.ace_character {\ +color: #AFA472\ +}\ +.ace-pastel-on-dark .ace_constant.ace_language {\ +color: #DE8E30\ +}\ +.ace-pastel-on-dark .ace_constant.ace_numeric {\ +color: #CCCCCC\ +}\ +.ace-pastel-on-dark .ace_invalid,\ +.ace-pastel-on-dark .ace_invalid.ace_illegal {\ +color: #F8F8F8;\ +background-color: rgba(86, 45, 86, 0.75)\ +}\ +.ace-pastel-on-dark .ace_invalid.ace_deprecated {\ +text-decoration: underline;\ +font-style: italic;\ +color: #D2A8A1\ +}\ +.ace-pastel-on-dark .ace_fold {\ +background-color: #757aD8;\ +border-color: #8F938F\ +}\ +.ace-pastel-on-dark .ace_support.ace_function {\ +color: #AEB2F8\ +}\ +.ace-pastel-on-dark .ace_string {\ +color: #66A968\ +}\ +.ace-pastel-on-dark .ace_string.ace_regexp {\ +color: #E9C062\ +}\ +.ace-pastel-on-dark .ace_comment {\ +color: #A6C6FF\ +}\ +.ace-pastel-on-dark .ace_variable {\ +color: #BEBF55\ +}\ +.ace-pastel-on-dark .ace_variable.ace_language {\ +color: #C1C144\ +}\ +.ace-pastel-on-dark .ace_xml-pe {\ +color: #494949\ +}\ +.ace-pastel-on-dark .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYIiPj/8PAARgAh2NTMh8AAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-solarized_dark.js b/modules/backend/assets/vendor/ace/theme-solarized_dark.js new file mode 100755 index 0000000..d1acdb4 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-solarized_dark.js @@ -0,0 +1,88 @@ +ace.define("ace/theme/solarized_dark",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-solarized-dark"; +exports.cssText = ".ace-solarized-dark .ace_gutter {\ +background: #01313f;\ +color: #d0edf7\ +}\ +.ace-solarized-dark .ace_print-margin {\ +width: 1px;\ +background: #33555E\ +}\ +.ace-solarized-dark {\ +background-color: #002B36;\ +color: #93A1A1\ +}\ +.ace-solarized-dark .ace_entity.ace_other.ace_attribute-name,\ +.ace-solarized-dark .ace_storage {\ +color: #93A1A1\ +}\ +.ace-solarized-dark .ace_cursor,\ +.ace-solarized-dark .ace_string.ace_regexp {\ +color: #D30102\ +}\ +.ace-solarized-dark .ace_marker-layer .ace_active-line,\ +.ace-solarized-dark .ace_marker-layer .ace_selection {\ +background: rgba(255, 255, 255, 0.1)\ +}\ +.ace-solarized-dark.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #002B36;\ +}\ +.ace-solarized-dark .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-solarized-dark .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgba(147, 161, 161, 0.50)\ +}\ +.ace-solarized-dark .ace_gutter-active-line {\ +background-color: #0d3440\ +}\ +.ace-solarized-dark .ace_marker-layer .ace_selected-word {\ +border: 1px solid #073642\ +}\ +.ace-solarized-dark .ace_invisible {\ +color: rgba(147, 161, 161, 0.50)\ +}\ +.ace-solarized-dark .ace_keyword,\ +.ace-solarized-dark .ace_meta,\ +.ace-solarized-dark .ace_support.ace_class,\ +.ace-solarized-dark .ace_support.ace_type {\ +color: #859900\ +}\ +.ace-solarized-dark .ace_constant.ace_character,\ +.ace-solarized-dark .ace_constant.ace_other {\ +color: #CB4B16\ +}\ +.ace-solarized-dark .ace_constant.ace_language {\ +color: #B58900\ +}\ +.ace-solarized-dark .ace_constant.ace_numeric {\ +color: #D33682\ +}\ +.ace-solarized-dark .ace_fold {\ +background-color: #268BD2;\ +border-color: #93A1A1\ +}\ +.ace-solarized-dark .ace_entity.ace_name.ace_function,\ +.ace-solarized-dark .ace_entity.ace_name.ace_tag,\ +.ace-solarized-dark .ace_support.ace_function,\ +.ace-solarized-dark .ace_variable,\ +.ace-solarized-dark .ace_variable.ace_language {\ +color: #268BD2\ +}\ +.ace-solarized-dark .ace_string {\ +color: #2AA198\ +}\ +.ace-solarized-dark .ace_comment {\ +font-style: italic;\ +color: #657B83\ +}\ +.ace-solarized-dark .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNg0Db1ZVCxc/sPAAd4AlUHlLenAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-solarized_light.js b/modules/backend/assets/vendor/ace/theme-solarized_light.js new file mode 100755 index 0000000..f0c078a --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-solarized_light.js @@ -0,0 +1,91 @@ +ace.define("ace/theme/solarized_light",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = false; +exports.cssClass = "ace-solarized-light"; +exports.cssText = ".ace-solarized-light .ace_gutter {\ +background: #fbf1d3;\ +color: #333\ +}\ +.ace-solarized-light .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8\ +}\ +.ace-solarized-light {\ +background-color: #FDF6E3;\ +color: #586E75\ +}\ +.ace-solarized-light .ace_cursor {\ +color: #000000\ +}\ +.ace-solarized-light .ace_marker-layer .ace_selection {\ +background: rgba(7, 54, 67, 0.09)\ +}\ +.ace-solarized-light.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #FDF6E3;\ +}\ +.ace-solarized-light .ace_marker-layer .ace_step {\ +background: rgb(255, 255, 0)\ +}\ +.ace-solarized-light .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgba(147, 161, 161, 0.50)\ +}\ +.ace-solarized-light .ace_marker-layer .ace_active-line {\ +background: #EEE8D5\ +}\ +.ace-solarized-light .ace_gutter-active-line {\ +background-color : #EDE5C1\ +}\ +.ace-solarized-light .ace_marker-layer .ace_selected-word {\ +border: 1px solid #073642\ +}\ +.ace-solarized-light .ace_invisible {\ +color: rgba(147, 161, 161, 0.50)\ +}\ +.ace-solarized-light .ace_keyword,\ +.ace-solarized-light .ace_meta,\ +.ace-solarized-light .ace_support.ace_class,\ +.ace-solarized-light .ace_support.ace_type {\ +color: #859900\ +}\ +.ace-solarized-light .ace_constant.ace_character,\ +.ace-solarized-light .ace_constant.ace_other {\ +color: #CB4B16\ +}\ +.ace-solarized-light .ace_constant.ace_language {\ +color: #B58900\ +}\ +.ace-solarized-light .ace_constant.ace_numeric {\ +color: #D33682\ +}\ +.ace-solarized-light .ace_fold {\ +background-color: #268BD2;\ +border-color: #586E75\ +}\ +.ace-solarized-light .ace_entity.ace_name.ace_function,\ +.ace-solarized-light .ace_entity.ace_name.ace_tag,\ +.ace-solarized-light .ace_support.ace_function,\ +.ace-solarized-light .ace_variable,\ +.ace-solarized-light .ace_variable.ace_language {\ +color: #268BD2\ +}\ +.ace-solarized-light .ace_storage {\ +color: #073642\ +}\ +.ace-solarized-light .ace_string {\ +color: #2AA198\ +}\ +.ace-solarized-light .ace_string.ace_regexp {\ +color: #D30102\ +}\ +.ace-solarized-light .ace_comment,\ +.ace-solarized-light .ace_entity.ace_other.ace_attribute-name {\ +color: #93A1A1\ +}\ +.ace-solarized-light .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYHjy8NJ/AAjgA5fzQUmBAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-sqlserver.js b/modules/backend/assets/vendor/ace/theme-sqlserver.js new file mode 100755 index 0000000..91f34f6 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-sqlserver.js @@ -0,0 +1,138 @@ +ace.define("ace/theme/sqlserver",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = false; +exports.cssClass = "ace-sqlserver"; +exports.cssText = ".ace-sqlserver .ace_gutter {\ +background: #ebebeb;\ +color: #333;\ +overflow: hidden;\ +}\ +.ace-sqlserver .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8;\ +}\ +.ace-sqlserver {\ +background-color: #FFFFFF;\ +color: black;\ +}\ +.ace-sqlserver .ace_identifier {\ +color: black;\ +}\ +.ace-sqlserver .ace_keyword {\ +color: #0000FF;\ +}\ +.ace-sqlserver .ace_numeric {\ +color: black;\ +}\ +.ace-sqlserver .ace_storage {\ +color: #11B7BE;\ +}\ +.ace-sqlserver .ace_keyword.ace_operator,\ +.ace-sqlserver .ace_lparen,\ +.ace-sqlserver .ace_rparen,\ +.ace-sqlserver .ace_punctuation {\ +color: #808080;\ +}\ +.ace-sqlserver .ace_set.ace_statement {\ +color: #0000FF;\ +text-decoration: underline;\ +}\ +.ace-sqlserver .ace_cursor {\ +color: black;\ +}\ +.ace-sqlserver .ace_invisible {\ +color: rgb(191, 191, 191);\ +}\ +.ace-sqlserver .ace_constant.ace_buildin {\ +color: rgb(88, 72, 246);\ +}\ +.ace-sqlserver .ace_constant.ace_language {\ +color: #979797;\ +}\ +.ace-sqlserver .ace_constant.ace_library {\ +color: rgb(6, 150, 14);\ +}\ +.ace-sqlserver .ace_invalid {\ +background-color: rgb(153, 0, 0);\ +color: white;\ +}\ +.ace-sqlserver .ace_support.ace_function {\ +color: #FF00FF;\ +}\ +.ace-sqlserver .ace_support.ace_constant {\ +color: rgb(6, 150, 14);\ +}\ +.ace-sqlserver .ace_class {\ +color: #008080;\ +}\ +.ace-sqlserver .ace_support.ace_other {\ +color: #6D79DE;\ +}\ +.ace-sqlserver .ace_variable.ace_parameter {\ +font-style: italic;\ +color: #FD971F;\ +}\ +.ace-sqlserver .ace_comment {\ +color: #008000;\ +}\ +.ace-sqlserver .ace_constant.ace_numeric {\ +color: black;\ +}\ +.ace-sqlserver .ace_variable {\ +color: rgb(49, 132, 149);\ +}\ +.ace-sqlserver .ace_xml-pe {\ +color: rgb(104, 104, 91);\ +}\ +.ace-sqlserver .ace_support.ace_storedprocedure {\ +color: #800000;\ +}\ +.ace-sqlserver .ace_heading {\ +color: rgb(12, 7, 255);\ +}\ +.ace-sqlserver .ace_list {\ +color: rgb(185, 6, 144);\ +}\ +.ace-sqlserver .ace_marker-layer .ace_selection {\ +background: rgb(181, 213, 255);\ +}\ +.ace-sqlserver .ace_marker-layer .ace_step {\ +background: rgb(252, 255, 0);\ +}\ +.ace-sqlserver .ace_marker-layer .ace_stack {\ +background: rgb(164, 229, 101);\ +}\ +.ace-sqlserver .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgb(192, 192, 192);\ +}\ +.ace-sqlserver .ace_marker-layer .ace_active-line {\ +background: rgba(0, 0, 0, 0.07);\ +}\ +.ace-sqlserver .ace_gutter-active-line {\ +background-color: #dcdcdc;\ +}\ +.ace-sqlserver .ace_marker-layer .ace_selected-word {\ +background: rgb(250, 250, 255);\ +border: 1px solid rgb(200, 200, 250);\ +}\ +.ace-sqlserver .ace_meta.ace_tag {\ +color: #0000FF;\ +}\ +.ace-sqlserver .ace_string.ace_regex {\ +color: #FF0000;\ +}\ +.ace-sqlserver .ace_string {\ +color: #FF0000;\ +}\ +.ace-sqlserver .ace_entity.ace_other.ace_attribute-name {\ +color: #994409;\ +}\ +.ace-sqlserver .ace_indent-guide {\ +background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\ +}\ +"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-terminal.js b/modules/backend/assets/vendor/ace/theme-terminal.js new file mode 100755 index 0000000..def9e69 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-terminal.js @@ -0,0 +1,114 @@ +ace.define("ace/theme/terminal",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-terminal-theme"; +exports.cssText = ".ace-terminal-theme .ace_gutter {\ +background: #1a0005;\ +color: steelblue\ +}\ +.ace-terminal-theme .ace_print-margin {\ +width: 1px;\ +background: #1a1a1a\ +}\ +.ace-terminal-theme {\ +background-color: black;\ +color: #DEDEDE\ +}\ +.ace-terminal-theme .ace_cursor {\ +color: #9F9F9F\ +}\ +.ace-terminal-theme .ace_marker-layer .ace_selection {\ +background: #424242\ +}\ +.ace-terminal-theme.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px black;\ +}\ +.ace-terminal-theme .ace_marker-layer .ace_step {\ +background: rgb(0, 0, 0)\ +}\ +.ace-terminal-theme .ace_marker-layer .ace_bracket {\ +background: #090;\ +}\ +.ace-terminal-theme .ace_marker-layer .ace_bracket-start {\ +background: #090;\ +}\ +.ace-terminal-theme .ace_marker-layer .ace_bracket-unmatched {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #900\ +}\ +.ace-terminal-theme .ace_marker-layer .ace_active-line {\ +background: #2A2A2A\ +}\ +.ace-terminal-theme .ace_gutter-active-line {\ +background-color: #2A112A\ +}\ +.ace-terminal-theme .ace_marker-layer .ace_selected-word {\ +border: 1px solid #424242\ +}\ +.ace-terminal-theme .ace_invisible {\ +color: #343434\ +}\ +.ace-terminal-theme .ace_keyword,\ +.ace-terminal-theme .ace_meta,\ +.ace-terminal-theme .ace_storage,\ +.ace-terminal-theme .ace_storage.ace_type,\ +.ace-terminal-theme .ace_support.ace_type {\ +color: tomato\ +}\ +.ace-terminal-theme .ace_keyword.ace_operator {\ +color: deeppink\ +}\ +.ace-terminal-theme .ace_constant.ace_character,\ +.ace-terminal-theme .ace_constant.ace_language,\ +.ace-terminal-theme .ace_constant.ace_numeric,\ +.ace-terminal-theme .ace_keyword.ace_other.ace_unit,\ +.ace-terminal-theme .ace_support.ace_constant,\ +.ace-terminal-theme .ace_variable.ace_parameter {\ +color: #E78C45\ +}\ +.ace-terminal-theme .ace_constant.ace_other {\ +color: gold\ +}\ +.ace-terminal-theme .ace_invalid {\ +color: yellow;\ +background-color: red\ +}\ +.ace-terminal-theme .ace_invalid.ace_deprecated {\ +color: #CED2CF;\ +background-color: #B798BF\ +}\ +.ace-terminal-theme .ace_fold {\ +background-color: #7AA6DA;\ +border-color: #DEDEDE\ +}\ +.ace-terminal-theme .ace_entity.ace_name.ace_function,\ +.ace-terminal-theme .ace_support.ace_function,\ +.ace-terminal-theme .ace_variable {\ +color: #7AA6DA\ +}\ +.ace-terminal-theme .ace_support.ace_class,\ +.ace-terminal-theme .ace_support.ace_type {\ +color: #E7C547\ +}\ +.ace-terminal-theme .ace_heading,\ +.ace-terminal-theme .ace_string {\ +color: #B9CA4A\ +}\ +.ace-terminal-theme .ace_entity.ace_name.ace_tag,\ +.ace-terminal-theme .ace_entity.ace_other.ace_attribute-name,\ +.ace-terminal-theme .ace_meta.ace_tag,\ +.ace-terminal-theme .ace_string.ace_regexp,\ +.ace-terminal-theme .ace_variable {\ +color: #D54E53\ +}\ +.ace-terminal-theme .ace_comment {\ +color: orangered\ +}\ +.ace-terminal-theme .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYLBWV/8PAAK4AYnhiq+xAAAAAElFTkSuQmCC) right repeat-y;\ +}\ +"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-textmate.js b/modules/backend/assets/vendor/ace/theme-textmate.js new file mode 100755 index 0000000..0033eda --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-textmate.js @@ -0,0 +1,129 @@ +ace.define("ace/theme/textmate",["require","exports","module","ace/lib/dom"], function(require, exports, module) { +"use strict"; + +exports.isDark = false; +exports.cssClass = "ace-tm"; +exports.cssText = ".ace-tm .ace_gutter {\ +background: #f0f0f0;\ +color: #333;\ +}\ +.ace-tm .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8;\ +}\ +.ace-tm .ace_fold {\ +background-color: #6B72E6;\ +}\ +.ace-tm {\ +background-color: #FFFFFF;\ +color: black;\ +}\ +.ace-tm .ace_cursor {\ +color: black;\ +}\ +.ace-tm .ace_invisible {\ +color: rgb(191, 191, 191);\ +}\ +.ace-tm .ace_storage,\ +.ace-tm .ace_keyword {\ +color: blue;\ +}\ +.ace-tm .ace_constant {\ +color: rgb(197, 6, 11);\ +}\ +.ace-tm .ace_constant.ace_buildin {\ +color: rgb(88, 72, 246);\ +}\ +.ace-tm .ace_constant.ace_language {\ +color: rgb(88, 92, 246);\ +}\ +.ace-tm .ace_constant.ace_library {\ +color: rgb(6, 150, 14);\ +}\ +.ace-tm .ace_invalid {\ +background-color: rgba(255, 0, 0, 0.1);\ +color: red;\ +}\ +.ace-tm .ace_support.ace_function {\ +color: rgb(60, 76, 114);\ +}\ +.ace-tm .ace_support.ace_constant {\ +color: rgb(6, 150, 14);\ +}\ +.ace-tm .ace_support.ace_type,\ +.ace-tm .ace_support.ace_class {\ +color: rgb(109, 121, 222);\ +}\ +.ace-tm .ace_keyword.ace_operator {\ +color: rgb(104, 118, 135);\ +}\ +.ace-tm .ace_string {\ +color: rgb(3, 106, 7);\ +}\ +.ace-tm .ace_comment {\ +color: rgb(76, 136, 107);\ +}\ +.ace-tm .ace_comment.ace_doc {\ +color: rgb(0, 102, 255);\ +}\ +.ace-tm .ace_comment.ace_doc.ace_tag {\ +color: rgb(128, 159, 191);\ +}\ +.ace-tm .ace_constant.ace_numeric {\ +color: rgb(0, 0, 205);\ +}\ +.ace-tm .ace_variable {\ +color: rgb(49, 132, 149);\ +}\ +.ace-tm .ace_xml-pe {\ +color: rgb(104, 104, 91);\ +}\ +.ace-tm .ace_entity.ace_name.ace_function {\ +color: #0000A2;\ +}\ +.ace-tm .ace_heading {\ +color: rgb(12, 7, 255);\ +}\ +.ace-tm .ace_list {\ +color:rgb(185, 6, 144);\ +}\ +.ace-tm .ace_meta.ace_tag {\ +color:rgb(0, 22, 142);\ +}\ +.ace-tm .ace_string.ace_regex {\ +color: rgb(255, 0, 0)\ +}\ +.ace-tm .ace_marker-layer .ace_selection {\ +background: rgb(181, 213, 255);\ +}\ +.ace-tm.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px white;\ +}\ +.ace-tm .ace_marker-layer .ace_step {\ +background: rgb(252, 255, 0);\ +}\ +.ace-tm .ace_marker-layer .ace_stack {\ +background: rgb(164, 229, 101);\ +}\ +.ace-tm .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgb(192, 192, 192);\ +}\ +.ace-tm .ace_marker-layer .ace_active-line {\ +background: rgba(0, 0, 0, 0.07);\ +}\ +.ace-tm .ace_gutter-active-line {\ +background-color : #dcdcdc;\ +}\ +.ace-tm .ace_marker-layer .ace_selected-word {\ +background: rgb(250, 250, 255);\ +border: 1px solid rgb(200, 200, 250);\ +}\ +.ace-tm .ace_indent-guide {\ +background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\ +}\ +"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-tomorrow.js b/modules/backend/assets/vendor/ace/theme-tomorrow.js new file mode 100755 index 0000000..4661be1 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-tomorrow.js @@ -0,0 +1,108 @@ +ace.define("ace/theme/tomorrow",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = false; +exports.cssClass = "ace-tomorrow"; +exports.cssText = ".ace-tomorrow .ace_gutter {\ +background: #f6f6f6;\ +color: #4D4D4C\ +}\ +.ace-tomorrow .ace_print-margin {\ +width: 1px;\ +background: #f6f6f6\ +}\ +.ace-tomorrow {\ +background-color: #FFFFFF;\ +color: #4D4D4C\ +}\ +.ace-tomorrow .ace_cursor {\ +color: #AEAFAD\ +}\ +.ace-tomorrow .ace_marker-layer .ace_selection {\ +background: #D6D6D6\ +}\ +.ace-tomorrow.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #FFFFFF;\ +}\ +.ace-tomorrow .ace_marker-layer .ace_step {\ +background: rgb(255, 255, 0)\ +}\ +.ace-tomorrow .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #D1D1D1\ +}\ +.ace-tomorrow .ace_marker-layer .ace_active-line {\ +background: #EFEFEF\ +}\ +.ace-tomorrow .ace_gutter-active-line {\ +background-color : #dcdcdc\ +}\ +.ace-tomorrow .ace_marker-layer .ace_selected-word {\ +border: 1px solid #D6D6D6\ +}\ +.ace-tomorrow .ace_invisible {\ +color: #D1D1D1\ +}\ +.ace-tomorrow .ace_keyword,\ +.ace-tomorrow .ace_meta,\ +.ace-tomorrow .ace_storage,\ +.ace-tomorrow .ace_storage.ace_type,\ +.ace-tomorrow .ace_support.ace_type {\ +color: #8959A8\ +}\ +.ace-tomorrow .ace_keyword.ace_operator {\ +color: #3E999F\ +}\ +.ace-tomorrow .ace_constant.ace_character,\ +.ace-tomorrow .ace_constant.ace_language,\ +.ace-tomorrow .ace_constant.ace_numeric,\ +.ace-tomorrow .ace_keyword.ace_other.ace_unit,\ +.ace-tomorrow .ace_support.ace_constant,\ +.ace-tomorrow .ace_variable.ace_parameter {\ +color: #F5871F\ +}\ +.ace-tomorrow .ace_constant.ace_other {\ +color: #666969\ +}\ +.ace-tomorrow .ace_invalid {\ +color: #FFFFFF;\ +background-color: #C82829\ +}\ +.ace-tomorrow .ace_invalid.ace_deprecated {\ +color: #FFFFFF;\ +background-color: #8959A8\ +}\ +.ace-tomorrow .ace_fold {\ +background-color: #4271AE;\ +border-color: #4D4D4C\ +}\ +.ace-tomorrow .ace_entity.ace_name.ace_function,\ +.ace-tomorrow .ace_support.ace_function,\ +.ace-tomorrow .ace_variable {\ +color: #4271AE\ +}\ +.ace-tomorrow .ace_support.ace_class,\ +.ace-tomorrow .ace_support.ace_type {\ +color: #C99E00\ +}\ +.ace-tomorrow .ace_heading,\ +.ace-tomorrow .ace_markup.ace_heading,\ +.ace-tomorrow .ace_string {\ +color: #718C00\ +}\ +.ace-tomorrow .ace_entity.ace_name.ace_tag,\ +.ace-tomorrow .ace_entity.ace_other.ace_attribute-name,\ +.ace-tomorrow .ace_meta.ace_tag,\ +.ace-tomorrow .ace_string.ace_regexp,\ +.ace-tomorrow .ace_variable {\ +color: #C82829\ +}\ +.ace-tomorrow .ace_comment {\ +color: #8E908C\ +}\ +.ace-tomorrow .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bdu3f/BwAlfgctduB85QAAAABJRU5ErkJggg==) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-tomorrow_night.js b/modules/backend/assets/vendor/ace/theme-tomorrow_night.js new file mode 100755 index 0000000..53e1f39 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-tomorrow_night.js @@ -0,0 +1,108 @@ +ace.define("ace/theme/tomorrow_night",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-tomorrow-night"; +exports.cssText = ".ace-tomorrow-night .ace_gutter {\ +background: #25282c;\ +color: #C5C8C6\ +}\ +.ace-tomorrow-night .ace_print-margin {\ +width: 1px;\ +background: #25282c\ +}\ +.ace-tomorrow-night {\ +background-color: #1D1F21;\ +color: #C5C8C6\ +}\ +.ace-tomorrow-night .ace_cursor {\ +color: #AEAFAD\ +}\ +.ace-tomorrow-night .ace_marker-layer .ace_selection {\ +background: #373B41\ +}\ +.ace-tomorrow-night.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #1D1F21;\ +}\ +.ace-tomorrow-night .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-tomorrow-night .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #4B4E55\ +}\ +.ace-tomorrow-night .ace_marker-layer .ace_active-line {\ +background: #282A2E\ +}\ +.ace-tomorrow-night .ace_gutter-active-line {\ +background-color: #282A2E\ +}\ +.ace-tomorrow-night .ace_marker-layer .ace_selected-word {\ +border: 1px solid #373B41\ +}\ +.ace-tomorrow-night .ace_invisible {\ +color: #4B4E55\ +}\ +.ace-tomorrow-night .ace_keyword,\ +.ace-tomorrow-night .ace_meta,\ +.ace-tomorrow-night .ace_storage,\ +.ace-tomorrow-night .ace_storage.ace_type,\ +.ace-tomorrow-night .ace_support.ace_type {\ +color: #B294BB\ +}\ +.ace-tomorrow-night .ace_keyword.ace_operator {\ +color: #8ABEB7\ +}\ +.ace-tomorrow-night .ace_constant.ace_character,\ +.ace-tomorrow-night .ace_constant.ace_language,\ +.ace-tomorrow-night .ace_constant.ace_numeric,\ +.ace-tomorrow-night .ace_keyword.ace_other.ace_unit,\ +.ace-tomorrow-night .ace_support.ace_constant,\ +.ace-tomorrow-night .ace_variable.ace_parameter {\ +color: #DE935F\ +}\ +.ace-tomorrow-night .ace_constant.ace_other {\ +color: #CED1CF\ +}\ +.ace-tomorrow-night .ace_invalid {\ +color: #CED2CF;\ +background-color: #DF5F5F\ +}\ +.ace-tomorrow-night .ace_invalid.ace_deprecated {\ +color: #CED2CF;\ +background-color: #B798BF\ +}\ +.ace-tomorrow-night .ace_fold {\ +background-color: #81A2BE;\ +border-color: #C5C8C6\ +}\ +.ace-tomorrow-night .ace_entity.ace_name.ace_function,\ +.ace-tomorrow-night .ace_support.ace_function,\ +.ace-tomorrow-night .ace_variable {\ +color: #81A2BE\ +}\ +.ace-tomorrow-night .ace_support.ace_class,\ +.ace-tomorrow-night .ace_support.ace_type {\ +color: #F0C674\ +}\ +.ace-tomorrow-night .ace_heading,\ +.ace-tomorrow-night .ace_markup.ace_heading,\ +.ace-tomorrow-night .ace_string {\ +color: #B5BD68\ +}\ +.ace-tomorrow-night .ace_entity.ace_name.ace_tag,\ +.ace-tomorrow-night .ace_entity.ace_other.ace_attribute-name,\ +.ace-tomorrow-night .ace_meta.ace_tag,\ +.ace-tomorrow-night .ace_string.ace_regexp,\ +.ace-tomorrow-night .ace_variable {\ +color: #CC6666\ +}\ +.ace-tomorrow-night .ace_comment {\ +color: #969896\ +}\ +.ace-tomorrow-night .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYHB3d/8PAAOIAdULw8qMAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-tomorrow_night_blue.js b/modules/backend/assets/vendor/ace/theme-tomorrow_night_blue.js new file mode 100755 index 0000000..956e221 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-tomorrow_night_blue.js @@ -0,0 +1,106 @@ +ace.define("ace/theme/tomorrow_night_blue",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-tomorrow-night-blue"; +exports.cssText = ".ace-tomorrow-night-blue .ace_gutter {\ +background: #00204b;\ +color: #7388b5\ +}\ +.ace-tomorrow-night-blue .ace_print-margin {\ +width: 1px;\ +background: #00204b\ +}\ +.ace-tomorrow-night-blue {\ +background-color: #002451;\ +color: #FFFFFF\ +}\ +.ace-tomorrow-night-blue .ace_constant.ace_other,\ +.ace-tomorrow-night-blue .ace_cursor {\ +color: #FFFFFF\ +}\ +.ace-tomorrow-night-blue .ace_marker-layer .ace_selection {\ +background: #003F8E\ +}\ +.ace-tomorrow-night-blue.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #002451;\ +}\ +.ace-tomorrow-night-blue .ace_marker-layer .ace_step {\ +background: rgb(127, 111, 19)\ +}\ +.ace-tomorrow-night-blue .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #404F7D\ +}\ +.ace-tomorrow-night-blue .ace_marker-layer .ace_active-line {\ +background: #00346E\ +}\ +.ace-tomorrow-night-blue .ace_gutter-active-line {\ +background-color: #022040\ +}\ +.ace-tomorrow-night-blue .ace_marker-layer .ace_selected-word {\ +border: 1px solid #003F8E\ +}\ +.ace-tomorrow-night-blue .ace_invisible {\ +color: #404F7D\ +}\ +.ace-tomorrow-night-blue .ace_keyword,\ +.ace-tomorrow-night-blue .ace_meta,\ +.ace-tomorrow-night-blue .ace_storage,\ +.ace-tomorrow-night-blue .ace_storage.ace_type,\ +.ace-tomorrow-night-blue .ace_support.ace_type {\ +color: #EBBBFF\ +}\ +.ace-tomorrow-night-blue .ace_keyword.ace_operator {\ +color: #99FFFF\ +}\ +.ace-tomorrow-night-blue .ace_constant.ace_character,\ +.ace-tomorrow-night-blue .ace_constant.ace_language,\ +.ace-tomorrow-night-blue .ace_constant.ace_numeric,\ +.ace-tomorrow-night-blue .ace_keyword.ace_other.ace_unit,\ +.ace-tomorrow-night-blue .ace_support.ace_constant,\ +.ace-tomorrow-night-blue .ace_variable.ace_parameter {\ +color: #FFC58F\ +}\ +.ace-tomorrow-night-blue .ace_invalid {\ +color: #FFFFFF;\ +background-color: #F99DA5\ +}\ +.ace-tomorrow-night-blue .ace_invalid.ace_deprecated {\ +color: #FFFFFF;\ +background-color: #EBBBFF\ +}\ +.ace-tomorrow-night-blue .ace_fold {\ +background-color: #BBDAFF;\ +border-color: #FFFFFF\ +}\ +.ace-tomorrow-night-blue .ace_entity.ace_name.ace_function,\ +.ace-tomorrow-night-blue .ace_support.ace_function,\ +.ace-tomorrow-night-blue .ace_variable {\ +color: #BBDAFF\ +}\ +.ace-tomorrow-night-blue .ace_support.ace_class,\ +.ace-tomorrow-night-blue .ace_support.ace_type {\ +color: #FFEEAD\ +}\ +.ace-tomorrow-night-blue .ace_heading,\ +.ace-tomorrow-night-blue .ace_markup.ace_heading,\ +.ace-tomorrow-night-blue .ace_string {\ +color: #D1F1A9\ +}\ +.ace-tomorrow-night-blue .ace_entity.ace_name.ace_tag,\ +.ace-tomorrow-night-blue .ace_entity.ace_other.ace_attribute-name,\ +.ace-tomorrow-night-blue .ace_meta.ace_tag,\ +.ace-tomorrow-night-blue .ace_string.ace_regexp,\ +.ace-tomorrow-night-blue .ace_variable {\ +color: #FF9DA4\ +}\ +.ace-tomorrow-night-blue .ace_comment {\ +color: #7285B7\ +}\ +.ace-tomorrow-night-blue .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYJDzqfwPAANXAeNsiA+ZAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-tomorrow_night_bright.js b/modules/backend/assets/vendor/ace/theme-tomorrow_night_bright.js new file mode 100755 index 0000000..8514a0d --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-tomorrow_night_bright.js @@ -0,0 +1,121 @@ +ace.define("ace/theme/tomorrow_night_bright",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-tomorrow-night-bright"; +exports.cssText = ".ace-tomorrow-night-bright .ace_gutter {\ +background: #1a1a1a;\ +color: #DEDEDE\ +}\ +.ace-tomorrow-night-bright .ace_print-margin {\ +width: 1px;\ +background: #1a1a1a\ +}\ +.ace-tomorrow-night-bright {\ +background-color: #000000;\ +color: #DEDEDE\ +}\ +.ace-tomorrow-night-bright .ace_cursor {\ +color: #9F9F9F\ +}\ +.ace-tomorrow-night-bright .ace_marker-layer .ace_selection {\ +background: #424242\ +}\ +.ace-tomorrow-night-bright.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #000000;\ +}\ +.ace-tomorrow-night-bright .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-tomorrow-night-bright .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #888888\ +}\ +.ace-tomorrow-night-bright .ace_marker-layer .ace_highlight {\ +border: 1px solid rgb(110, 119, 0);\ +border-bottom: 0;\ +box-shadow: inset 0 -1px rgb(110, 119, 0);\ +margin: -1px 0 0 -1px;\ +background: rgba(255, 235, 0, 0.1)\ +}\ +.ace-tomorrow-night-bright .ace_marker-layer .ace_active-line {\ +background: #2A2A2A\ +}\ +.ace-tomorrow-night-bright .ace_gutter-active-line {\ +background-color: #2A2A2A\ +}\ +.ace-tomorrow-night-bright .ace_stack {\ +background-color: rgb(66, 90, 44)\ +}\ +.ace-tomorrow-night-bright .ace_marker-layer .ace_selected-word {\ +border: 1px solid #888888\ +}\ +.ace-tomorrow-night-bright .ace_invisible {\ +color: #343434\ +}\ +.ace-tomorrow-night-bright .ace_keyword,\ +.ace-tomorrow-night-bright .ace_meta,\ +.ace-tomorrow-night-bright .ace_storage,\ +.ace-tomorrow-night-bright .ace_storage.ace_type,\ +.ace-tomorrow-night-bright .ace_support.ace_type {\ +color: #C397D8\ +}\ +.ace-tomorrow-night-bright .ace_keyword.ace_operator {\ +color: #70C0B1\ +}\ +.ace-tomorrow-night-bright .ace_constant.ace_character,\ +.ace-tomorrow-night-bright .ace_constant.ace_language,\ +.ace-tomorrow-night-bright .ace_constant.ace_numeric,\ +.ace-tomorrow-night-bright .ace_keyword.ace_other.ace_unit,\ +.ace-tomorrow-night-bright .ace_support.ace_constant,\ +.ace-tomorrow-night-bright .ace_variable.ace_parameter {\ +color: #E78C45\ +}\ +.ace-tomorrow-night-bright .ace_constant.ace_other {\ +color: #EEEEEE\ +}\ +.ace-tomorrow-night-bright .ace_invalid {\ +color: #CED2CF;\ +background-color: #DF5F5F\ +}\ +.ace-tomorrow-night-bright .ace_invalid.ace_deprecated {\ +color: #CED2CF;\ +background-color: #B798BF\ +}\ +.ace-tomorrow-night-bright .ace_fold {\ +background-color: #7AA6DA;\ +border-color: #DEDEDE\ +}\ +.ace-tomorrow-night-bright .ace_entity.ace_name.ace_function,\ +.ace-tomorrow-night-bright .ace_support.ace_function,\ +.ace-tomorrow-night-bright .ace_variable {\ +color: #7AA6DA\ +}\ +.ace-tomorrow-night-bright .ace_support.ace_class,\ +.ace-tomorrow-night-bright .ace_support.ace_type {\ +color: #E7C547\ +}\ +.ace-tomorrow-night-bright .ace_heading,\ +.ace-tomorrow-night-bright .ace_markup.ace_heading,\ +.ace-tomorrow-night-bright .ace_string {\ +color: #B9CA4A\ +}\ +.ace-tomorrow-night-bright .ace_entity.ace_name.ace_tag,\ +.ace-tomorrow-night-bright .ace_entity.ace_other.ace_attribute-name,\ +.ace-tomorrow-night-bright .ace_meta.ace_tag,\ +.ace-tomorrow-night-bright .ace_string.ace_regexp,\ +.ace-tomorrow-night-bright .ace_variable {\ +color: #D54E53\ +}\ +.ace-tomorrow-night-bright .ace_comment {\ +color: #969896\ +}\ +.ace-tomorrow-night-bright .ace_c9searchresults.ace_keyword {\ +color: #C2C280\ +}\ +.ace-tomorrow-night-bright .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYFBXV/8PAAJoAXX4kT2EAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-tomorrow_night_eighties.js b/modules/backend/assets/vendor/ace/theme-tomorrow_night_eighties.js new file mode 100755 index 0000000..3665e3f --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-tomorrow_night_eighties.js @@ -0,0 +1,108 @@ +ace.define("ace/theme/tomorrow_night_eighties",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-tomorrow-night-eighties"; +exports.cssText = ".ace-tomorrow-night-eighties .ace_gutter {\ +background: #272727;\ +color: #CCC\ +}\ +.ace-tomorrow-night-eighties .ace_print-margin {\ +width: 1px;\ +background: #272727\ +}\ +.ace-tomorrow-night-eighties {\ +background-color: #2D2D2D;\ +color: #CCCCCC\ +}\ +.ace-tomorrow-night-eighties .ace_constant.ace_other,\ +.ace-tomorrow-night-eighties .ace_cursor {\ +color: #CCCCCC\ +}\ +.ace-tomorrow-night-eighties .ace_marker-layer .ace_selection {\ +background: #515151\ +}\ +.ace-tomorrow-night-eighties.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #2D2D2D;\ +}\ +.ace-tomorrow-night-eighties .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-tomorrow-night-eighties .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #6A6A6A\ +}\ +.ace-tomorrow-night-bright .ace_stack {\ +background: rgb(66, 90, 44)\ +}\ +.ace-tomorrow-night-eighties .ace_marker-layer .ace_active-line {\ +background: #393939\ +}\ +.ace-tomorrow-night-eighties .ace_gutter-active-line {\ +background-color: #393939\ +}\ +.ace-tomorrow-night-eighties .ace_marker-layer .ace_selected-word {\ +border: 1px solid #515151\ +}\ +.ace-tomorrow-night-eighties .ace_invisible {\ +color: #6A6A6A\ +}\ +.ace-tomorrow-night-eighties .ace_keyword,\ +.ace-tomorrow-night-eighties .ace_meta,\ +.ace-tomorrow-night-eighties .ace_storage,\ +.ace-tomorrow-night-eighties .ace_storage.ace_type,\ +.ace-tomorrow-night-eighties .ace_support.ace_type {\ +color: #CC99CC\ +}\ +.ace-tomorrow-night-eighties .ace_keyword.ace_operator {\ +color: #66CCCC\ +}\ +.ace-tomorrow-night-eighties .ace_constant.ace_character,\ +.ace-tomorrow-night-eighties .ace_constant.ace_language,\ +.ace-tomorrow-night-eighties .ace_constant.ace_numeric,\ +.ace-tomorrow-night-eighties .ace_keyword.ace_other.ace_unit,\ +.ace-tomorrow-night-eighties .ace_support.ace_constant,\ +.ace-tomorrow-night-eighties .ace_variable.ace_parameter {\ +color: #F99157\ +}\ +.ace-tomorrow-night-eighties .ace_invalid {\ +color: #CDCDCD;\ +background-color: #F2777A\ +}\ +.ace-tomorrow-night-eighties .ace_invalid.ace_deprecated {\ +color: #CDCDCD;\ +background-color: #CC99CC\ +}\ +.ace-tomorrow-night-eighties .ace_fold {\ +background-color: #6699CC;\ +border-color: #CCCCCC\ +}\ +.ace-tomorrow-night-eighties .ace_entity.ace_name.ace_function,\ +.ace-tomorrow-night-eighties .ace_support.ace_function,\ +.ace-tomorrow-night-eighties .ace_variable {\ +color: #6699CC\ +}\ +.ace-tomorrow-night-eighties .ace_support.ace_class,\ +.ace-tomorrow-night-eighties .ace_support.ace_type {\ +color: #FFCC66\ +}\ +.ace-tomorrow-night-eighties .ace_heading,\ +.ace-tomorrow-night-eighties .ace_markup.ace_heading,\ +.ace-tomorrow-night-eighties .ace_string {\ +color: #99CC99\ +}\ +.ace-tomorrow-night-eighties .ace_comment {\ +color: #999999\ +}\ +.ace-tomorrow-night-eighties .ace_entity.ace_name.ace_tag,\ +.ace-tomorrow-night-eighties .ace_entity.ace_other.ace_attribute-name,\ +.ace-tomorrow-night-eighties .ace_meta.ace_tag,\ +.ace-tomorrow-night-eighties .ace_variable {\ +color: #F2777A\ +}\ +.ace-tomorrow-night-eighties .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWPQ09NrYAgMjP4PAAtGAwchHMyAAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-twilight.js b/modules/backend/assets/vendor/ace/theme-twilight.js new file mode 100755 index 0000000..48ec030 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-twilight.js @@ -0,0 +1,109 @@ +ace.define("ace/theme/twilight",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-twilight"; +exports.cssText = ".ace-twilight .ace_gutter {\ +background: #232323;\ +color: #E2E2E2\ +}\ +.ace-twilight .ace_print-margin {\ +width: 1px;\ +background: #232323\ +}\ +.ace-twilight {\ +background-color: #141414;\ +color: #F8F8F8\ +}\ +.ace-twilight .ace_cursor {\ +color: #A7A7A7\ +}\ +.ace-twilight .ace_marker-layer .ace_selection {\ +background: rgba(221, 240, 255, 0.20)\ +}\ +.ace-twilight.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #141414;\ +}\ +.ace-twilight .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-twilight .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid rgba(255, 255, 255, 0.25)\ +}\ +.ace-twilight .ace_marker-layer .ace_active-line {\ +background: rgba(255, 255, 255, 0.031)\ +}\ +.ace-twilight .ace_gutter-active-line {\ +background-color: rgba(255, 255, 255, 0.031)\ +}\ +.ace-twilight .ace_marker-layer .ace_selected-word {\ +border: 1px solid rgba(221, 240, 255, 0.20)\ +}\ +.ace-twilight .ace_invisible {\ +color: rgba(255, 255, 255, 0.25)\ +}\ +.ace-twilight .ace_keyword,\ +.ace-twilight .ace_meta {\ +color: #CDA869\ +}\ +.ace-twilight .ace_constant,\ +.ace-twilight .ace_constant.ace_character,\ +.ace-twilight .ace_constant.ace_character.ace_escape,\ +.ace-twilight .ace_constant.ace_other,\ +.ace-twilight .ace_heading,\ +.ace-twilight .ace_markup.ace_heading,\ +.ace-twilight .ace_support.ace_constant {\ +color: #CF6A4C\ +}\ +.ace-twilight .ace_invalid.ace_illegal {\ +color: #F8F8F8;\ +background-color: rgba(86, 45, 86, 0.75)\ +}\ +.ace-twilight .ace_invalid.ace_deprecated {\ +text-decoration: underline;\ +font-style: italic;\ +color: #D2A8A1\ +}\ +.ace-twilight .ace_support {\ +color: #9B859D\ +}\ +.ace-twilight .ace_fold {\ +background-color: #AC885B;\ +border-color: #F8F8F8\ +}\ +.ace-twilight .ace_support.ace_function {\ +color: #DAD085\ +}\ +.ace-twilight .ace_list,\ +.ace-twilight .ace_markup.ace_list,\ +.ace-twilight .ace_storage {\ +color: #F9EE98\ +}\ +.ace-twilight .ace_entity.ace_name.ace_function,\ +.ace-twilight .ace_meta.ace_tag,\ +.ace-twilight .ace_variable {\ +color: #AC885B\ +}\ +.ace-twilight .ace_string {\ +color: #8F9D6A\ +}\ +.ace-twilight .ace_string.ace_regexp {\ +color: #E9C062\ +}\ +.ace-twilight .ace_comment {\ +font-style: italic;\ +color: #5F5A60\ +}\ +.ace-twilight .ace_variable {\ +color: #7587A6\ +}\ +.ace-twilight .ace_xml-pe {\ +color: #494949\ +}\ +.ace-twilight .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWMQERFpYLC1tf0PAAgOAnPnhxyiAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-vibrant_ink.js b/modules/backend/assets/vendor/ace/theme-vibrant_ink.js new file mode 100755 index 0000000..db926c7 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-vibrant_ink.js @@ -0,0 +1,94 @@ +ace.define("ace/theme/vibrant_ink",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = true; +exports.cssClass = "ace-vibrant-ink"; +exports.cssText = ".ace-vibrant-ink .ace_gutter {\ +background: #1a1a1a;\ +color: #BEBEBE\ +}\ +.ace-vibrant-ink .ace_print-margin {\ +width: 1px;\ +background: #1a1a1a\ +}\ +.ace-vibrant-ink {\ +background-color: #0F0F0F;\ +color: #FFFFFF\ +}\ +.ace-vibrant-ink .ace_cursor {\ +color: #FFFFFF\ +}\ +.ace-vibrant-ink .ace_marker-layer .ace_selection {\ +background: #6699CC\ +}\ +.ace-vibrant-ink.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #0F0F0F;\ +}\ +.ace-vibrant-ink .ace_marker-layer .ace_step {\ +background: rgb(102, 82, 0)\ +}\ +.ace-vibrant-ink .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #404040\ +}\ +.ace-vibrant-ink .ace_marker-layer .ace_active-line {\ +background: #333333\ +}\ +.ace-vibrant-ink .ace_gutter-active-line {\ +background-color: #333333\ +}\ +.ace-vibrant-ink .ace_marker-layer .ace_selected-word {\ +border: 1px solid #6699CC\ +}\ +.ace-vibrant-ink .ace_invisible {\ +color: #404040\ +}\ +.ace-vibrant-ink .ace_keyword,\ +.ace-vibrant-ink .ace_meta {\ +color: #FF6600\ +}\ +.ace-vibrant-ink .ace_constant,\ +.ace-vibrant-ink .ace_constant.ace_character,\ +.ace-vibrant-ink .ace_constant.ace_character.ace_escape,\ +.ace-vibrant-ink .ace_constant.ace_other {\ +color: #339999\ +}\ +.ace-vibrant-ink .ace_constant.ace_numeric {\ +color: #99CC99\ +}\ +.ace-vibrant-ink .ace_invalid,\ +.ace-vibrant-ink .ace_invalid.ace_deprecated {\ +color: #CCFF33;\ +background-color: #000000\ +}\ +.ace-vibrant-ink .ace_fold {\ +background-color: #FFCC00;\ +border-color: #FFFFFF\ +}\ +.ace-vibrant-ink .ace_entity.ace_name.ace_function,\ +.ace-vibrant-ink .ace_support.ace_function,\ +.ace-vibrant-ink .ace_variable {\ +color: #FFCC00\ +}\ +.ace-vibrant-ink .ace_variable.ace_parameter {\ +font-style: italic\ +}\ +.ace-vibrant-ink .ace_string {\ +color: #66FF00\ +}\ +.ace-vibrant-ink .ace_string.ace_regexp {\ +color: #44B4CC\ +}\ +.ace-vibrant-ink .ace_comment {\ +color: #9933CC\ +}\ +.ace-vibrant-ink .ace_entity.ace_other.ace_attribute-name {\ +font-style: italic;\ +color: #99CC99\ +}\ +.ace-vibrant-ink .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAEklEQVQImWNgYGBgYNDTc/oPAALPAZ7hxlbYAAAAAElFTkSuQmCC) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/theme-xcode.js b/modules/backend/assets/vendor/ace/theme-xcode.js new file mode 100755 index 0000000..3604a17 --- /dev/null +++ b/modules/backend/assets/vendor/ace/theme-xcode.js @@ -0,0 +1,88 @@ +ace.define("ace/theme/xcode",["require","exports","module","ace/lib/dom"], function(require, exports, module) { + +exports.isDark = false; +exports.cssClass = "ace-xcode"; +exports.cssText = "\ +.ace-xcode .ace_gutter {\ +background: #e8e8e8;\ +color: #333\ +}\ +.ace-xcode .ace_print-margin {\ +width: 1px;\ +background: #e8e8e8\ +}\ +.ace-xcode {\ +background-color: #FFFFFF;\ +color: #000000\ +}\ +.ace-xcode .ace_cursor {\ +color: #000000\ +}\ +.ace-xcode .ace_marker-layer .ace_selection {\ +background: #B5D5FF\ +}\ +.ace-xcode.ace_multiselect .ace_selection.ace_start {\ +box-shadow: 0 0 3px 0px #FFFFFF;\ +}\ +.ace-xcode .ace_marker-layer .ace_step {\ +background: rgb(198, 219, 174)\ +}\ +.ace-xcode .ace_marker-layer .ace_bracket {\ +margin: -1px 0 0 -1px;\ +border: 1px solid #BFBFBF\ +}\ +.ace-xcode .ace_marker-layer .ace_active-line {\ +background: rgba(0, 0, 0, 0.071)\ +}\ +.ace-xcode .ace_gutter-active-line {\ +background-color: rgba(0, 0, 0, 0.071)\ +}\ +.ace-xcode .ace_marker-layer .ace_selected-word {\ +border: 1px solid #B5D5FF\ +}\ +.ace-xcode .ace_constant.ace_language,\ +.ace-xcode .ace_keyword,\ +.ace-xcode .ace_meta,\ +.ace-xcode .ace_variable.ace_language {\ +color: #C800A4\ +}\ +.ace-xcode .ace_invisible {\ +color: #BFBFBF\ +}\ +.ace-xcode .ace_constant.ace_character,\ +.ace-xcode .ace_constant.ace_other {\ +color: #275A5E\ +}\ +.ace-xcode .ace_constant.ace_numeric {\ +color: #3A00DC\ +}\ +.ace-xcode .ace_entity.ace_other.ace_attribute-name,\ +.ace-xcode .ace_support.ace_constant,\ +.ace-xcode .ace_support.ace_function {\ +color: #450084\ +}\ +.ace-xcode .ace_fold {\ +background-color: #C800A4;\ +border-color: #000000\ +}\ +.ace-xcode .ace_entity.ace_name.ace_tag,\ +.ace-xcode .ace_support.ace_class,\ +.ace-xcode .ace_support.ace_type {\ +color: #790EAD\ +}\ +.ace-xcode .ace_storage {\ +color: #C900A4\ +}\ +.ace-xcode .ace_string {\ +color: #DF0002\ +}\ +.ace-xcode .ace_comment {\ +color: #008E00\ +}\ +.ace-xcode .ace_indent-guide {\ +background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==) right repeat-y\ +}"; + +var dom = require("../lib/dom"); +dom.importCssString(exports.cssText, exports.cssClass); +}); diff --git a/modules/backend/assets/vendor/ace/worker-css.js b/modules/backend/assets/vendor/ace/worker-css.js new file mode 100755 index 0000000..28774f7 --- /dev/null +++ b/modules/backend/assets/vendor/ace/worker-css.js @@ -0,0 +1,8762 @@ +"no use strict"; +;(function(window) { +if (typeof window.window != "undefined" && window.document) + return; +if (window.require && window.define) + return; + +if (!window.console) { + window.console = function() { + var msgs = Array.prototype.slice.call(arguments, 0); + postMessage({type: "log", data: msgs}); + }; + window.console.error = + window.console.warn = + window.console.log = + window.console.trace = window.console; +} +window.window = window; +window.ace = window; + +window.onerror = function(message, file, line, col, err) { + postMessage({type: "error", data: { + message: message, + data: err.data, + file: file, + line: line, + col: col, + stack: err.stack + }}); +}; + +window.normalizeModule = function(parentId, moduleName) { + // normalize plugin requires + if (moduleName.indexOf("!") !== -1) { + var chunks = moduleName.split("!"); + return window.normalizeModule(parentId, chunks[0]) + "!" + window.normalizeModule(parentId, chunks[1]); + } + // normalize relative requires + if (moduleName.charAt(0) == ".") { + var base = parentId.split("/").slice(0, -1).join("/"); + moduleName = (base ? base + "/" : "") + moduleName; + + while (moduleName.indexOf(".") !== -1 && previous != moduleName) { + var previous = moduleName; + moduleName = moduleName.replace(/^\.\//, "").replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, ""); + } + } + + return moduleName; +}; + +window.require = function require(parentId, id) { + if (!id) { + id = parentId; + parentId = null; + } + if (!id.charAt) + throw new Error("worker.js require() accepts only (parentId, id) as arguments"); + + id = window.normalizeModule(parentId, id); + + var module = window.require.modules[id]; + if (module) { + if (!module.initialized) { + module.initialized = true; + module.exports = module.factory().exports; + } + return module.exports; + } + + if (!window.require.tlns) + return console.log("unable to load " + id); + + var path = resolveModuleId(id, window.require.tlns); + if (path.slice(-3) != ".js") path += ".js"; + + window.require.id = id; + window.require.modules[id] = {}; // prevent infinite loop on broken modules + importScripts(path); + return window.require(parentId, id); +}; +function resolveModuleId(id, paths) { + var testPath = id, tail = ""; + while (testPath) { + var alias = paths[testPath]; + if (typeof alias == "string") { + return alias + tail; + } else if (alias) { + return alias.location.replace(/\/*$/, "/") + (tail || alias.main || alias.name); + } else if (alias === false) { + return ""; + } + var i = testPath.lastIndexOf("/"); + if (i === -1) break; + tail = testPath.substr(i) + tail; + testPath = testPath.slice(0, i); + } + return id; +} +window.require.modules = {}; +window.require.tlns = {}; + +window.define = function(id, deps, factory) { + if (arguments.length == 2) { + factory = deps; + if (typeof id != "string") { + deps = id; + id = window.require.id; + } + } else if (arguments.length == 1) { + factory = id; + deps = []; + id = window.require.id; + } + + if (typeof factory != "function") { + window.require.modules[id] = { + exports: factory, + initialized: true + }; + return; + } + + if (!deps.length) + // If there is no dependencies, we inject "require", "exports" and + // "module" as dependencies, to provide CommonJS compatibility. + deps = ["require", "exports", "module"]; + + var req = function(childId) { + return window.require(id, childId); + }; + + window.require.modules[id] = { + exports: {}, + factory: function() { + var module = this; + var returnExports = factory.apply(this, deps.map(function(dep) { + switch (dep) { + // Because "require", "exports" and "module" aren't actual + // dependencies, we must handle them seperately. + case "require": return req; + case "exports": return module.exports; + case "module": return module; + // But for all other dependencies, we can just go ahead and + // require them. + default: return req(dep); + } + })); + if (returnExports) + module.exports = returnExports; + return module; + } + }; +}; +window.define.amd = {}; +require.tlns = {}; +window.initBaseUrls = function initBaseUrls(topLevelNamespaces) { + for (var i in topLevelNamespaces) + require.tlns[i] = topLevelNamespaces[i]; +}; + +window.initSender = function initSender() { + + var EventEmitter = window.require("ace/lib/event_emitter").EventEmitter; + var oop = window.require("ace/lib/oop"); + + var Sender = function() {}; + + (function() { + + oop.implement(this, EventEmitter); + + this.callback = function(data, callbackId) { + postMessage({ + type: "call", + id: callbackId, + data: data + }); + }; + + this.emit = function(name, data) { + postMessage({ + type: "event", + name: name, + data: data + }); + }; + + }).call(Sender.prototype); + + return new Sender(); +}; + +var main = window.main = null; +var sender = window.sender = null; + +window.onmessage = function(e) { + var msg = e.data; + if (msg.event && sender) { + sender._signal(msg.event, msg.data); + } + else if (msg.command) { + if (main[msg.command]) + main[msg.command].apply(main, msg.args); + else if (window[msg.command]) + window[msg.command].apply(window, msg.args); + else + throw new Error("Unknown command:" + msg.command); + } + else if (msg.init) { + window.initBaseUrls(msg.tlns); + require("ace/lib/es5-shim"); + sender = window.sender = window.initSender(); + var clazz = require(msg.module)[msg.classname]; + main = window.main = new clazz(sender); + } +}; +})(this); + +ace.define("ace/lib/oop",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.inherits = function(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); +}; + +exports.mixin = function(obj, mixin) { + for (var key in mixin) { + obj[key] = mixin[key]; + } + return obj; +}; + +exports.implement = function(proto, mixin) { + exports.mixin(proto, mixin); +}; + +}); + +ace.define("ace/lib/lang",["require","exports","module"], function(require, exports, module) { +"use strict"; + +exports.last = function(a) { + return a[a.length - 1]; +}; + +exports.stringReverse = function(string) { + return string.split("").reverse().join(""); +}; + +exports.stringRepeat = function (string, count) { + var result = ''; + while (count > 0) { + if (count & 1) + result += string; + + if (count >>= 1) + string += string; + } + return result; +}; + +var trimBeginRegexp = /^\s\s*/; +var trimEndRegexp = /\s\s*$/; + +exports.stringTrimLeft = function (string) { + return string.replace(trimBeginRegexp, ''); +}; + +exports.stringTrimRight = function (string) { + return string.replace(trimEndRegexp, ''); +}; + +exports.copyObject = function(obj) { + var copy = {}; + for (var key in obj) { + copy[key] = obj[key]; + } + return copy; +}; + +exports.copyArray = function(array){ + var copy = []; + for (var i=0, l=array.length; i [" + this.end.row + "/" + this.end.column + "]"); + }; + + this.contains = function(row, column) { + return this.compare(row, column) == 0; + }; + this.compareRange = function(range) { + var cmp, + end = range.end, + start = range.start; + + cmp = this.compare(end.row, end.column); + if (cmp == 1) { + cmp = this.compare(start.row, start.column); + if (cmp == 1) { + return 2; + } else if (cmp == 0) { + return 1; + } else { + return 0; + } + } else if (cmp == -1) { + return -2; + } else { + cmp = this.compare(start.row, start.column); + if (cmp == -1) { + return -1; + } else if (cmp == 1) { + return 42; + } else { + return 0; + } + } + }; + this.comparePoint = function(p) { + return this.compare(p.row, p.column); + }; + this.containsRange = function(range) { + return this.comparePoint(range.start) == 0 && this.comparePoint(range.end) == 0; + }; + this.intersects = function(range) { + var cmp = this.compareRange(range); + return (cmp == -1 || cmp == 0 || cmp == 1); + }; + this.isEnd = function(row, column) { + return this.end.row == row && this.end.column == column; + }; + this.isStart = function(row, column) { + return this.start.row == row && this.start.column == column; + }; + this.setStart = function(row, column) { + if (typeof row == "object") { + this.start.column = row.column; + this.start.row = row.row; + } else { + this.start.row = row; + this.start.column = column; + } + }; + this.setEnd = function(row, column) { + if (typeof row == "object") { + this.end.column = row.column; + this.end.row = row.row; + } else { + this.end.row = row; + this.end.column = column; + } + }; + this.inside = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column) || this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.insideStart = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isEnd(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.insideEnd = function(row, column) { + if (this.compare(row, column) == 0) { + if (this.isStart(row, column)) { + return false; + } else { + return true; + } + } + return false; + }; + this.compare = function(row, column) { + if (!this.isMultiLine()) { + if (row === this.start.row) { + return column < this.start.column ? -1 : (column > this.end.column ? 1 : 0); + } + } + + if (row < this.start.row) + return -1; + + if (row > this.end.row) + return 1; + + if (this.start.row === row) + return column >= this.start.column ? 0 : -1; + + if (this.end.row === row) + return column <= this.end.column ? 0 : 1; + + return 0; + }; + this.compareStart = function(row, column) { + if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + }; + this.compareEnd = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else { + return this.compare(row, column); + } + }; + this.compareInside = function(row, column) { + if (this.end.row == row && this.end.column == column) { + return 1; + } else if (this.start.row == row && this.start.column == column) { + return -1; + } else { + return this.compare(row, column); + } + }; + this.clipRows = function(firstRow, lastRow) { + if (this.end.row > lastRow) + var end = {row: lastRow + 1, column: 0}; + else if (this.end.row < firstRow) + var end = {row: firstRow, column: 0}; + + if (this.start.row > lastRow) + var start = {row: lastRow + 1, column: 0}; + else if (this.start.row < firstRow) + var start = {row: firstRow, column: 0}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + this.extend = function(row, column) { + var cmp = this.compare(row, column); + + if (cmp == 0) + return this; + else if (cmp == -1) + var start = {row: row, column: column}; + else + var end = {row: row, column: column}; + + return Range.fromPoints(start || this.start, end || this.end); + }; + + this.isEmpty = function() { + return (this.start.row === this.end.row && this.start.column === this.end.column); + }; + this.isMultiLine = function() { + return (this.start.row !== this.end.row); + }; + this.clone = function() { + return Range.fromPoints(this.start, this.end); + }; + this.collapseRows = function() { + if (this.end.column == 0) + return new Range(this.start.row, 0, Math.max(this.start.row, this.end.row-1), 0) + else + return new Range(this.start.row, 0, this.end.row, 0) + }; + this.toScreenRange = function(session) { + var screenPosStart = session.documentToScreenPosition(this.start); + var screenPosEnd = session.documentToScreenPosition(this.end); + + return new Range( + screenPosStart.row, screenPosStart.column, + screenPosEnd.row, screenPosEnd.column + ); + }; + this.moveBy = function(row, column) { + this.start.row += row; + this.start.column += column; + this.end.row += row; + this.end.column += column; + }; + +}).call(Range.prototype); +Range.fromPoints = function(start, end) { + return new Range(start.row, start.column, end.row, end.column); +}; +Range.comparePoints = comparePoints; + +Range.comparePoints = function(p1, p2) { + return p1.row - p2.row || p1.column - p2.column; +}; + + +exports.Range = Range; +}); + +ace.define("ace/apply_delta",["require","exports","module"], function(require, exports, module) { +"use strict"; + +function throwDeltaError(delta, errorText){ + console.log("Invalid Delta:", delta); + throw "Invalid Delta: " + errorText; +} + +function positionInDocument(docLines, position) { + return position.row >= 0 && position.row < docLines.length && + position.column >= 0 && position.column <= docLines[position.row].length; +} + +function validateDelta(docLines, delta) { + if (delta.action != "insert" && delta.action != "remove") + throwDeltaError(delta, "delta.action must be 'insert' or 'remove'"); + if (!(delta.lines instanceof Array)) + throwDeltaError(delta, "delta.lines must be an Array"); + if (!delta.start || !delta.end) + throwDeltaError(delta, "delta.start/end must be an present"); + var start = delta.start; + if (!positionInDocument(docLines, delta.start)) + throwDeltaError(delta, "delta.start must be contained in document"); + var end = delta.end; + if (delta.action == "remove" && !positionInDocument(docLines, end)) + throwDeltaError(delta, "delta.end must contained in document for 'remove' actions"); + var numRangeRows = end.row - start.row; + var numRangeLastLineChars = (end.column - (numRangeRows == 0 ? start.column : 0)); + if (numRangeRows != delta.lines.length - 1 || delta.lines[numRangeRows].length != numRangeLastLineChars) + throwDeltaError(delta, "delta.range must match delta lines"); +} + +exports.applyDelta = function(docLines, delta, doNotValidate) { + + var row = delta.start.row; + var startColumn = delta.start.column; + var line = docLines[row] || ""; + switch (delta.action) { + case "insert": + var lines = delta.lines; + if (lines.length === 1) { + docLines[row] = line.substring(0, startColumn) + delta.lines[0] + line.substring(startColumn); + } else { + var args = [row, 1].concat(delta.lines); + docLines.splice.apply(docLines, args); + docLines[row] = line.substring(0, startColumn) + docLines[row]; + docLines[row + delta.lines.length - 1] += line.substring(startColumn); + } + break; + case "remove": + var endColumn = delta.end.column; + var endRow = delta.end.row; + if (row === endRow) { + docLines[row] = line.substring(0, startColumn) + line.substring(endColumn); + } else { + docLines.splice( + row, endRow - row + 1, + line.substring(0, startColumn) + docLines[endRow].substring(endColumn) + ); + } + break; + } +} +}); + +ace.define("ace/lib/event_emitter",["require","exports","module"], function(require, exports, module) { +"use strict"; + +var EventEmitter = {}; +var stopPropagation = function() { this.propagationStopped = true; }; +var preventDefault = function() { this.defaultPrevented = true; }; + +EventEmitter._emit = +EventEmitter._dispatchEvent = function(eventName, e) { + this._eventRegistry || (this._eventRegistry = {}); + this._defaultHandlers || (this._defaultHandlers = {}); + + var listeners = this._eventRegistry[eventName] || []; + var defaultHandler = this._defaultHandlers[eventName]; + if (!listeners.length && !defaultHandler) + return; + + if (typeof e != "object" || !e) + e = {}; + + if (!e.type) + e.type = eventName; + if (!e.stopPropagation) + e.stopPropagation = stopPropagation; + if (!e.preventDefault) + e.preventDefault = preventDefault; + + listeners = listeners.slice(); + for (var i=0; i this.row) + return; + + var point = $getTransformedPoint(delta, {row: this.row, column: this.column}, this.$insertRight); + this.setPosition(point.row, point.column, true); + }; + + function $pointsInOrder(point1, point2, equalPointsInOrder) { + var bColIsAfter = equalPointsInOrder ? point1.column <= point2.column : point1.column < point2.column; + return (point1.row < point2.row) || (point1.row == point2.row && bColIsAfter); + } + + function $getTransformedPoint(delta, point, moveIfEqual) { + var deltaIsInsert = delta.action == "insert"; + var deltaRowShift = (deltaIsInsert ? 1 : -1) * (delta.end.row - delta.start.row); + var deltaColShift = (deltaIsInsert ? 1 : -1) * (delta.end.column - delta.start.column); + var deltaStart = delta.start; + var deltaEnd = deltaIsInsert ? deltaStart : delta.end; // Collapse insert range. + if ($pointsInOrder(point, deltaStart, moveIfEqual)) { + return { + row: point.row, + column: point.column + }; + } + if ($pointsInOrder(deltaEnd, point, !moveIfEqual)) { + return { + row: point.row + deltaRowShift, + column: point.column + (point.row == deltaEnd.row ? deltaColShift : 0) + }; + } + + return { + row: deltaStart.row, + column: deltaStart.column + }; + } + this.setPosition = function(row, column, noClip) { + var pos; + if (noClip) { + pos = { + row: row, + column: column + }; + } else { + pos = this.$clipPositionToDocument(row, column); + } + + if (this.row == pos.row && this.column == pos.column) + return; + + var old = { + row: this.row, + column: this.column + }; + + this.row = pos.row; + this.column = pos.column; + this._signal("change", { + old: old, + value: pos + }); + }; + this.detach = function() { + this.document.removeEventListener("change", this.$onChange); + }; + this.attach = function(doc) { + this.document = doc || this.document; + this.document.on("change", this.$onChange); + }; + this.$clipPositionToDocument = function(row, column) { + var pos = {}; + + if (row >= this.document.getLength()) { + pos.row = Math.max(0, this.document.getLength() - 1); + pos.column = this.document.getLine(pos.row).length; + } + else if (row < 0) { + pos.row = 0; + pos.column = 0; + } + else { + pos.row = row; + pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); + } + + if (column < 0) + pos.column = 0; + + return pos; + }; + +}).call(Anchor.prototype); + +}); + +ace.define("ace/document",["require","exports","module","ace/lib/oop","ace/apply_delta","ace/lib/event_emitter","ace/range","ace/anchor"], function(require, exports, module) { +"use strict"; + +var oop = require("./lib/oop"); +var applyDelta = require("./apply_delta").applyDelta; +var EventEmitter = require("./lib/event_emitter").EventEmitter; +var Range = require("./range").Range; +var Anchor = require("./anchor").Anchor; + +var Document = function(textOrLines) { + this.$lines = [""]; + if (textOrLines.length === 0) { + this.$lines = [""]; + } else if (Array.isArray(textOrLines)) { + this.insertMergedLines({row: 0, column: 0}, textOrLines); + } else { + this.insert({row: 0, column:0}, textOrLines); + } +}; + +(function() { + + oop.implement(this, EventEmitter); + this.setValue = function(text) { + var len = this.getLength() - 1; + this.remove(new Range(0, 0, len, this.getLine(len).length)); + this.insert({row: 0, column: 0}, text); + }; + this.getValue = function() { + return this.getAllLines().join(this.getNewLineCharacter()); + }; + this.createAnchor = function(row, column) { + return new Anchor(this, row, column); + }; + if ("aaa".split(/a/).length === 0) { + this.$split = function(text) { + return text.replace(/\r\n|\r/g, "\n").split("\n"); + }; + } else { + this.$split = function(text) { + return text.split(/\r\n|\r|\n/); + }; + } + + + this.$detectNewLine = function(text) { + var match = text.match(/^.*?(\r\n|\r|\n)/m); + this.$autoNewLine = match ? match[1] : "\n"; + this._signal("changeNewLineMode"); + }; + this.getNewLineCharacter = function() { + switch (this.$newLineMode) { + case "windows": + return "\r\n"; + case "unix": + return "\n"; + default: + return this.$autoNewLine || "\n"; + } + }; + + this.$autoNewLine = ""; + this.$newLineMode = "auto"; + this.setNewLineMode = function(newLineMode) { + if (this.$newLineMode === newLineMode) + return; + + this.$newLineMode = newLineMode; + this._signal("changeNewLineMode"); + }; + this.getNewLineMode = function() { + return this.$newLineMode; + }; + this.isNewLine = function(text) { + return (text == "\r\n" || text == "\r" || text == "\n"); + }; + this.getLine = function(row) { + return this.$lines[row] || ""; + }; + this.getLines = function(firstRow, lastRow) { + return this.$lines.slice(firstRow, lastRow + 1); + }; + this.getAllLines = function() { + return this.getLines(0, this.getLength()); + }; + this.getLength = function() { + return this.$lines.length; + }; + this.getTextRange = function(range) { + return this.getLinesForRange(range).join(this.getNewLineCharacter()); + }; + this.getLinesForRange = function(range) { + var lines; + if (range.start.row === range.end.row) { + lines = [this.getLine(range.start.row).substring(range.start.column, range.end.column)]; + } else { + lines = this.getLines(range.start.row, range.end.row); + lines[0] = (lines[0] || "").substring(range.start.column); + var l = lines.length - 1; + if (range.end.row - range.start.row == l) + lines[l] = lines[l].substring(0, range.end.column); + } + return lines; + }; + this.insertLines = function(row, lines) { + console.warn("Use of document.insertLines is deprecated. Use the insertFullLines method instead."); + return this.insertFullLines(row, lines); + }; + this.removeLines = function(firstRow, lastRow) { + console.warn("Use of document.removeLines is deprecated. Use the removeFullLines method instead."); + return this.removeFullLines(firstRow, lastRow); + }; + this.insertNewLine = function(position) { + console.warn("Use of document.insertNewLine is deprecated. Use insertMergedLines(position, [\'\', \'\']) instead."); + return this.insertMergedLines(position, ["", ""]); + }; + this.insert = function(position, text) { + if (this.getLength() <= 1) + this.$detectNewLine(text); + + return this.insertMergedLines(position, this.$split(text)); + }; + this.insertInLine = function(position, text) { + var start = this.clippedPos(position.row, position.column); + var end = this.pos(position.row, position.column + text.length); + + this.applyDelta({ + start: start, + end: end, + action: "insert", + lines: [text] + }, true); + + return this.clonePos(end); + }; + + this.clippedPos = function(row, column) { + var length = this.getLength(); + if (row === undefined) { + row = length; + } else if (row < 0) { + row = 0; + } else if (row >= length) { + row = length - 1; + column = undefined; + } + var line = this.getLine(row); + if (column == undefined) + column = line.length; + column = Math.min(Math.max(column, 0), line.length); + return {row: row, column: column}; + }; + + this.clonePos = function(pos) { + return {row: pos.row, column: pos.column}; + }; + + this.pos = function(row, column) { + return {row: row, column: column}; + }; + + this.$clipPosition = function(position) { + var length = this.getLength(); + if (position.row >= length) { + position.row = Math.max(0, length - 1); + position.column = this.getLine(length - 1).length; + } else { + position.row = Math.max(0, position.row); + position.column = Math.min(Math.max(position.column, 0), this.getLine(position.row).length); + } + return position; + }; + this.insertFullLines = function(row, lines) { + row = Math.min(Math.max(row, 0), this.getLength()); + var column = 0; + if (row < this.getLength()) { + lines = lines.concat([""]); + column = 0; + } else { + lines = [""].concat(lines); + row--; + column = this.$lines[row].length; + } + this.insertMergedLines({row: row, column: column}, lines); + }; + this.insertMergedLines = function(position, lines) { + var start = this.clippedPos(position.row, position.column); + var end = { + row: start.row + lines.length - 1, + column: (lines.length == 1 ? start.column : 0) + lines[lines.length - 1].length + }; + + this.applyDelta({ + start: start, + end: end, + action: "insert", + lines: lines + }); + + return this.clonePos(end); + }; + this.remove = function(range) { + var start = this.clippedPos(range.start.row, range.start.column); + var end = this.clippedPos(range.end.row, range.end.column); + this.applyDelta({ + start: start, + end: end, + action: "remove", + lines: this.getLinesForRange({start: start, end: end}) + }); + return this.clonePos(start); + }; + this.removeInLine = function(row, startColumn, endColumn) { + var start = this.clippedPos(row, startColumn); + var end = this.clippedPos(row, endColumn); + + this.applyDelta({ + start: start, + end: end, + action: "remove", + lines: this.getLinesForRange({start: start, end: end}) + }, true); + + return this.clonePos(start); + }; + this.removeFullLines = function(firstRow, lastRow) { + firstRow = Math.min(Math.max(0, firstRow), this.getLength() - 1); + lastRow = Math.min(Math.max(0, lastRow ), this.getLength() - 1); + var deleteFirstNewLine = lastRow == this.getLength() - 1 && firstRow > 0; + var deleteLastNewLine = lastRow < this.getLength() - 1; + var startRow = ( deleteFirstNewLine ? firstRow - 1 : firstRow ); + var startCol = ( deleteFirstNewLine ? this.getLine(startRow).length : 0 ); + var endRow = ( deleteLastNewLine ? lastRow + 1 : lastRow ); + var endCol = ( deleteLastNewLine ? 0 : this.getLine(endRow).length ); + var range = new Range(startRow, startCol, endRow, endCol); + var deletedLines = this.$lines.slice(firstRow, lastRow + 1); + + this.applyDelta({ + start: range.start, + end: range.end, + action: "remove", + lines: this.getLinesForRange(range) + }); + return deletedLines; + }; + this.removeNewLine = function(row) { + if (row < this.getLength() - 1 && row >= 0) { + this.applyDelta({ + start: this.pos(row, this.getLine(row).length), + end: this.pos(row + 1, 0), + action: "remove", + lines: ["", ""] + }); + } + }; + this.replace = function(range, text) { + if (!(range instanceof Range)) + range = Range.fromPoints(range.start, range.end); + if (text.length === 0 && range.isEmpty()) + return range.start; + if (text == this.getTextRange(range)) + return range.end; + + this.remove(range); + var end; + if (text) { + end = this.insert(range.start, text); + } + else { + end = range.start; + } + + return end; + }; + this.applyDeltas = function(deltas) { + for (var i=0; i=0; i--) { + this.revertDelta(deltas[i]); + } + }; + this.applyDelta = function(delta, doNotValidate) { + var isInsert = delta.action == "insert"; + if (isInsert ? delta.lines.length <= 1 && !delta.lines[0] + : !Range.comparePoints(delta.start, delta.end)) { + return; + } + + if (isInsert && delta.lines.length > 20000) + this.$splitAndapplyLargeDelta(delta, 20000); + applyDelta(this.$lines, delta, doNotValidate); + this._signal("change", delta); + }; + + this.$splitAndapplyLargeDelta = function(delta, MAX) { + var lines = delta.lines; + var l = lines.length; + var row = delta.start.row; + var column = delta.start.column; + var from = 0, to = 0; + do { + from = to; + to += MAX - 1; + var chunk = lines.slice(from, to); + if (to > l) { + delta.lines = chunk; + delta.start.row = row + from; + delta.start.column = column; + break; + } + chunk.push(""); + this.applyDelta({ + start: this.pos(row + from, column), + end: this.pos(row + to, column = 0), + action: delta.action, + lines: chunk + }, true); + } while(true); + }; + this.revertDelta = function(delta) { + this.applyDelta({ + start: this.clonePos(delta.start), + end: this.clonePos(delta.end), + action: (delta.action == "insert" ? "remove" : "insert"), + lines: delta.lines.slice() + }); + }; + this.indexToPosition = function(index, startRow) { + var lines = this.$lines || this.getAllLines(); + var newlineLength = this.getNewLineCharacter().length; + for (var i = startRow || 0, l = lines.length; i < l; i++) { + index -= lines[i].length + newlineLength; + if (index < 0) + return {row: i, column: index + lines[i].length + newlineLength}; + } + return {row: l-1, column: lines[l-1].length}; + }; + this.positionToIndex = function(pos, startRow) { + var lines = this.$lines || this.getAllLines(); + var newlineLength = this.getNewLineCharacter().length; + var index = 0; + var row = Math.min(pos.row, lines.length); + for (var i = startRow || 0; i < row; ++i) + index += lines[i].length + newlineLength; + + return index + pos.column; + }; + +}).call(Document.prototype); + +exports.Document = Document; +}); + +ace.define("ace/worker/mirror",["require","exports","module","ace/range","ace/document","ace/lib/lang"], function(require, exports, module) { +"use strict"; + +var Range = require("../range").Range; +var Document = require("../document").Document; +var lang = require("../lib/lang"); + +var Mirror = exports.Mirror = function(sender) { + this.sender = sender; + var doc = this.doc = new Document(""); + + var deferredUpdate = this.deferredUpdate = lang.delayedCall(this.onUpdate.bind(this)); + + var _self = this; + sender.on("change", function(e) { + var data = e.data; + if (data[0].start) { + doc.applyDeltas(data); + } else { + for (var i = 0; i < data.length; i += 2) { + if (Array.isArray(data[i+1])) { + var d = {action: "insert", start: data[i], lines: data[i+1]}; + } else { + var d = {action: "remove", start: data[i], end: data[i+1]}; + } + doc.applyDelta(d, true); + } + } + if (_self.$timeout) + return deferredUpdate.schedule(_self.$timeout); + _self.onUpdate(); + }); +}; + +(function() { + + this.$timeout = 500; + + this.setTimeout = function(timeout) { + this.$timeout = timeout; + }; + + this.setValue = function(value) { + this.doc.setValue(value); + this.deferredUpdate.schedule(this.$timeout); + }; + + this.getValue = function(callbackId) { + this.sender.callback(this.doc.getValue(), callbackId); + }; + + this.onUpdate = function() { + }; + + this.isPending = function() { + return this.deferredUpdate.isPending(); + }; + +}).call(Mirror.prototype); + +}); + +ace.define("ace/mode/css/csslint",["require","exports","module"], function(require, exports, module) { +var parserlib = {}; +(function(){ +function EventTarget(){ + this._listeners = {}; +} + +EventTarget.prototype = { + constructor: EventTarget, + addListener: function(type, listener){ + if (!this._listeners[type]){ + this._listeners[type] = []; + } + + this._listeners[type].push(listener); + }, + fire: function(event){ + if (typeof event == "string"){ + event = { type: event }; + } + if (typeof event.target != "undefined"){ + event.target = this; + } + + if (typeof event.type == "undefined"){ + throw new Error("Event object missing 'type' property."); + } + + if (this._listeners[event.type]){ + var listeners = this._listeners[event.type].concat(); + for (var i=0, len=listeners.length; i < len; i++){ + listeners[i].call(this, event); + } + } + }, + removeListener: function(type, listener){ + if (this._listeners[type]){ + var listeners = this._listeners[type]; + for (var i=0, len=listeners.length; i < len; i++){ + if (listeners[i] === listener){ + listeners.splice(i, 1); + break; + } + } + + + } + } +}; +function StringReader(text){ + this._input = text.replace(/\n\r?/g, "\n"); + this._line = 1; + this._col = 1; + this._cursor = 0; +} + +StringReader.prototype = { + constructor: StringReader, + getCol: function(){ + return this._col; + }, + getLine: function(){ + return this._line ; + }, + eof: function(){ + return (this._cursor == this._input.length); + }, + peek: function(count){ + var c = null; + count = (typeof count == "undefined" ? 1 : count); + if (this._cursor < this._input.length){ + c = this._input.charAt(this._cursor + count - 1); + } + + return c; + }, + read: function(){ + var c = null; + if (this._cursor < this._input.length){ + if (this._input.charAt(this._cursor) == "\n"){ + this._line++; + this._col=1; + } else { + this._col++; + } + c = this._input.charAt(this._cursor++); + } + + return c; + }, + mark: function(){ + this._bookmark = { + cursor: this._cursor, + line: this._line, + col: this._col + }; + }, + + reset: function(){ + if (this._bookmark){ + this._cursor = this._bookmark.cursor; + this._line = this._bookmark.line; + this._col = this._bookmark.col; + delete this._bookmark; + } + }, + readTo: function(pattern){ + + var buffer = "", + c; + while (buffer.length < pattern.length || buffer.lastIndexOf(pattern) != buffer.length - pattern.length){ + c = this.read(); + if (c){ + buffer += c; + } else { + throw new Error("Expected \"" + pattern + "\" at line " + this._line + ", col " + this._col + "."); + } + } + + return buffer; + + }, + readWhile: function(filter){ + + var buffer = "", + c = this.read(); + + while(c !== null && filter(c)){ + buffer += c; + c = this.read(); + } + + return buffer; + + }, + readMatch: function(matcher){ + + var source = this._input.substring(this._cursor), + value = null; + if (typeof matcher == "string"){ + if (source.indexOf(matcher) === 0){ + value = this.readCount(matcher.length); + } + } else if (matcher instanceof RegExp){ + if (matcher.test(source)){ + value = this.readCount(RegExp.lastMatch.length); + } + } + + return value; + }, + readCount: function(count){ + var buffer = ""; + + while(count--){ + buffer += this.read(); + } + + return buffer; + } + +}; +function SyntaxError(message, line, col){ + this.col = col; + this.line = line; + this.message = message; + +} +SyntaxError.prototype = new Error(); +function SyntaxUnit(text, line, col, type){ + this.col = col; + this.line = line; + this.text = text; + this.type = type; +} +SyntaxUnit.fromToken = function(token){ + return new SyntaxUnit(token.value, token.startLine, token.startCol); +}; + +SyntaxUnit.prototype = { + constructor: SyntaxUnit, + valueOf: function(){ + return this.text; + }, + toString: function(){ + return this.text; + } + +}; +function TokenStreamBase(input, tokenData){ + this._reader = input ? new StringReader(input.toString()) : null; + this._token = null; + this._tokenData = tokenData; + this._lt = []; + this._ltIndex = 0; + + this._ltIndexCache = []; +} +TokenStreamBase.createTokenData = function(tokens){ + + var nameMap = [], + typeMap = {}, + tokenData = tokens.concat([]), + i = 0, + len = tokenData.length+1; + + tokenData.UNKNOWN = -1; + tokenData.unshift({name:"EOF"}); + + for (; i < len; i++){ + nameMap.push(tokenData[i].name); + tokenData[tokenData[i].name] = i; + if (tokenData[i].text){ + typeMap[tokenData[i].text] = i; + } + } + + tokenData.name = function(tt){ + return nameMap[tt]; + }; + + tokenData.type = function(c){ + return typeMap[c]; + }; + + return tokenData; +}; + +TokenStreamBase.prototype = { + constructor: TokenStreamBase, + match: function(tokenTypes, channel){ + if (!(tokenTypes instanceof Array)){ + tokenTypes = [tokenTypes]; + } + + var tt = this.get(channel), + i = 0, + len = tokenTypes.length; + + while(i < len){ + if (tt == tokenTypes[i++]){ + return true; + } + } + this.unget(); + return false; + }, + mustMatch: function(tokenTypes, channel){ + + var token; + if (!(tokenTypes instanceof Array)){ + tokenTypes = [tokenTypes]; + } + + if (!this.match.apply(this, arguments)){ + token = this.LT(1); + throw new SyntaxError("Expected " + this._tokenData[tokenTypes[0]].name + + " at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol); + } + }, + advance: function(tokenTypes, channel){ + + while(this.LA(0) !== 0 && !this.match(tokenTypes, channel)){ + this.get(); + } + + return this.LA(0); + }, + get: function(channel){ + + var tokenInfo = this._tokenData, + reader = this._reader, + value, + i =0, + len = tokenInfo.length, + found = false, + token, + info; + if (this._lt.length && this._ltIndex >= 0 && this._ltIndex < this._lt.length){ + + i++; + this._token = this._lt[this._ltIndex++]; + info = tokenInfo[this._token.type]; + while((info.channel !== undefined && channel !== info.channel) && + this._ltIndex < this._lt.length){ + this._token = this._lt[this._ltIndex++]; + info = tokenInfo[this._token.type]; + i++; + } + if ((info.channel === undefined || channel === info.channel) && + this._ltIndex <= this._lt.length){ + this._ltIndexCache.push(i); + return this._token.type; + } + } + token = this._getToken(); + if (token.type > -1 && !tokenInfo[token.type].hide){ + token.channel = tokenInfo[token.type].channel; + this._token = token; + this._lt.push(token); + this._ltIndexCache.push(this._lt.length - this._ltIndex + i); + if (this._lt.length > 5){ + this._lt.shift(); + } + if (this._ltIndexCache.length > 5){ + this._ltIndexCache.shift(); + } + this._ltIndex = this._lt.length; + } + info = tokenInfo[token.type]; + if (info && + (info.hide || + (info.channel !== undefined && channel !== info.channel))){ + return this.get(channel); + } else { + return token.type; + } + }, + LA: function(index){ + var total = index, + tt; + if (index > 0){ + if (index > 5){ + throw new Error("Too much lookahead."); + } + while(total){ + tt = this.get(); + total--; + } + while(total < index){ + this.unget(); + total++; + } + } else if (index < 0){ + + if(this._lt[this._ltIndex+index]){ + tt = this._lt[this._ltIndex+index].type; + } else { + throw new Error("Too much lookbehind."); + } + + } else { + tt = this._token.type; + } + + return tt; + + }, + LT: function(index){ + this.LA(index); + return this._lt[this._ltIndex+index-1]; + }, + peek: function(){ + return this.LA(1); + }, + token: function(){ + return this._token; + }, + tokenName: function(tokenType){ + if (tokenType < 0 || tokenType > this._tokenData.length){ + return "UNKNOWN_TOKEN"; + } else { + return this._tokenData[tokenType].name; + } + }, + tokenType: function(tokenName){ + return this._tokenData[tokenName] || -1; + }, + unget: function(){ + if (this._ltIndexCache.length){ + this._ltIndex -= this._ltIndexCache.pop();//--; + this._token = this._lt[this._ltIndex - 1]; + } else { + throw new Error("Too much lookahead."); + } + } + +}; + + +parserlib.util = { +StringReader: StringReader, +SyntaxError : SyntaxError, +SyntaxUnit : SyntaxUnit, +EventTarget : EventTarget, +TokenStreamBase : TokenStreamBase +}; +})(); +(function(){ +var EventTarget = parserlib.util.EventTarget, +TokenStreamBase = parserlib.util.TokenStreamBase, +StringReader = parserlib.util.StringReader, +SyntaxError = parserlib.util.SyntaxError, +SyntaxUnit = parserlib.util.SyntaxUnit; + +var Colors = { + aliceblue :"#f0f8ff", + antiquewhite :"#faebd7", + aqua :"#00ffff", + aquamarine :"#7fffd4", + azure :"#f0ffff", + beige :"#f5f5dc", + bisque :"#ffe4c4", + black :"#000000", + blanchedalmond :"#ffebcd", + blue :"#0000ff", + blueviolet :"#8a2be2", + brown :"#a52a2a", + burlywood :"#deb887", + cadetblue :"#5f9ea0", + chartreuse :"#7fff00", + chocolate :"#d2691e", + coral :"#ff7f50", + cornflowerblue :"#6495ed", + cornsilk :"#fff8dc", + crimson :"#dc143c", + cyan :"#00ffff", + darkblue :"#00008b", + darkcyan :"#008b8b", + darkgoldenrod :"#b8860b", + darkgray :"#a9a9a9", + darkgrey :"#a9a9a9", + darkgreen :"#006400", + darkkhaki :"#bdb76b", + darkmagenta :"#8b008b", + darkolivegreen :"#556b2f", + darkorange :"#ff8c00", + darkorchid :"#9932cc", + darkred :"#8b0000", + darksalmon :"#e9967a", + darkseagreen :"#8fbc8f", + darkslateblue :"#483d8b", + darkslategray :"#2f4f4f", + darkslategrey :"#2f4f4f", + darkturquoise :"#00ced1", + darkviolet :"#9400d3", + deeppink :"#ff1493", + deepskyblue :"#00bfff", + dimgray :"#696969", + dimgrey :"#696969", + dodgerblue :"#1e90ff", + firebrick :"#b22222", + floralwhite :"#fffaf0", + forestgreen :"#228b22", + fuchsia :"#ff00ff", + gainsboro :"#dcdcdc", + ghostwhite :"#f8f8ff", + gold :"#ffd700", + goldenrod :"#daa520", + gray :"#808080", + grey :"#808080", + green :"#008000", + greenyellow :"#adff2f", + honeydew :"#f0fff0", + hotpink :"#ff69b4", + indianred :"#cd5c5c", + indigo :"#4b0082", + ivory :"#fffff0", + khaki :"#f0e68c", + lavender :"#e6e6fa", + lavenderblush :"#fff0f5", + lawngreen :"#7cfc00", + lemonchiffon :"#fffacd", + lightblue :"#add8e6", + lightcoral :"#f08080", + lightcyan :"#e0ffff", + lightgoldenrodyellow :"#fafad2", + lightgray :"#d3d3d3", + lightgrey :"#d3d3d3", + lightgreen :"#90ee90", + lightpink :"#ffb6c1", + lightsalmon :"#ffa07a", + lightseagreen :"#20b2aa", + lightskyblue :"#87cefa", + lightslategray :"#778899", + lightslategrey :"#778899", + lightsteelblue :"#b0c4de", + lightyellow :"#ffffe0", + lime :"#00ff00", + limegreen :"#32cd32", + linen :"#faf0e6", + magenta :"#ff00ff", + maroon :"#800000", + mediumaquamarine:"#66cdaa", + mediumblue :"#0000cd", + mediumorchid :"#ba55d3", + mediumpurple :"#9370d8", + mediumseagreen :"#3cb371", + mediumslateblue :"#7b68ee", + mediumspringgreen :"#00fa9a", + mediumturquoise :"#48d1cc", + mediumvioletred :"#c71585", + midnightblue :"#191970", + mintcream :"#f5fffa", + mistyrose :"#ffe4e1", + moccasin :"#ffe4b5", + navajowhite :"#ffdead", + navy :"#000080", + oldlace :"#fdf5e6", + olive :"#808000", + olivedrab :"#6b8e23", + orange :"#ffa500", + orangered :"#ff4500", + orchid :"#da70d6", + palegoldenrod :"#eee8aa", + palegreen :"#98fb98", + paleturquoise :"#afeeee", + palevioletred :"#d87093", + papayawhip :"#ffefd5", + peachpuff :"#ffdab9", + peru :"#cd853f", + pink :"#ffc0cb", + plum :"#dda0dd", + powderblue :"#b0e0e6", + purple :"#800080", + red :"#ff0000", + rosybrown :"#bc8f8f", + royalblue :"#4169e1", + saddlebrown :"#8b4513", + salmon :"#fa8072", + sandybrown :"#f4a460", + seagreen :"#2e8b57", + seashell :"#fff5ee", + sienna :"#a0522d", + silver :"#c0c0c0", + skyblue :"#87ceeb", + slateblue :"#6a5acd", + slategray :"#708090", + slategrey :"#708090", + snow :"#fffafa", + springgreen :"#00ff7f", + steelblue :"#4682b4", + tan :"#d2b48c", + teal :"#008080", + thistle :"#d8bfd8", + tomato :"#ff6347", + turquoise :"#40e0d0", + violet :"#ee82ee", + wheat :"#f5deb3", + white :"#ffffff", + whitesmoke :"#f5f5f5", + yellow :"#ffff00", + yellowgreen :"#9acd32", + activeBorder :"Active window border.", + activecaption :"Active window caption.", + appworkspace :"Background color of multiple document interface.", + background :"Desktop background.", + buttonface :"The face background color for 3-D elements that appear 3-D due to one layer of surrounding border.", + buttonhighlight :"The color of the border facing the light source for 3-D elements that appear 3-D due to one layer of surrounding border.", + buttonshadow :"The color of the border away from the light source for 3-D elements that appear 3-D due to one layer of surrounding border.", + buttontext :"Text on push buttons.", + captiontext :"Text in caption, size box, and scrollbar arrow box.", + graytext :"Grayed (disabled) text. This color is set to #000 if the current display driver does not support a solid gray color.", + greytext :"Greyed (disabled) text. This color is set to #000 if the current display driver does not support a solid grey color.", + highlight :"Item(s) selected in a control.", + highlighttext :"Text of item(s) selected in a control.", + inactiveborder :"Inactive window border.", + inactivecaption :"Inactive window caption.", + inactivecaptiontext :"Color of text in an inactive caption.", + infobackground :"Background color for tooltip controls.", + infotext :"Text color for tooltip controls.", + menu :"Menu background.", + menutext :"Text in menus.", + scrollbar :"Scroll bar gray area.", + threeddarkshadow :"The color of the darker (generally outer) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + threedface :"The face background color for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + threedhighlight :"The color of the lighter (generally outer) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + threedlightshadow :"The color of the darker (generally inner) of the two borders facing the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + threedshadow :"The color of the lighter (generally inner) of the two borders away from the light source for 3-D elements that appear 3-D due to two concentric layers of surrounding border.", + window :"Window background.", + windowframe :"Window frame.", + windowtext :"Text in windows." +}; +function Combinator(text, line, col){ + + SyntaxUnit.call(this, text, line, col, Parser.COMBINATOR_TYPE); + this.type = "unknown"; + if (/^\s+$/.test(text)){ + this.type = "descendant"; + } else if (text == ">"){ + this.type = "child"; + } else if (text == "+"){ + this.type = "adjacent-sibling"; + } else if (text == "~"){ + this.type = "sibling"; + } + +} + +Combinator.prototype = new SyntaxUnit(); +Combinator.prototype.constructor = Combinator; +function MediaFeature(name, value){ + + SyntaxUnit.call(this, "(" + name + (value !== null ? ":" + value : "") + ")", name.startLine, name.startCol, Parser.MEDIA_FEATURE_TYPE); + this.name = name; + this.value = value; +} + +MediaFeature.prototype = new SyntaxUnit(); +MediaFeature.prototype.constructor = MediaFeature; +function MediaQuery(modifier, mediaType, features, line, col){ + + SyntaxUnit.call(this, (modifier ? modifier + " ": "") + (mediaType ? mediaType : "") + (mediaType && features.length > 0 ? " and " : "") + features.join(" and "), line, col, Parser.MEDIA_QUERY_TYPE); + this.modifier = modifier; + this.mediaType = mediaType; + this.features = features; + +} + +MediaQuery.prototype = new SyntaxUnit(); +MediaQuery.prototype.constructor = MediaQuery; +function Parser(options){ + EventTarget.call(this); + + + this.options = options || {}; + + this._tokenStream = null; +} +Parser.DEFAULT_TYPE = 0; +Parser.COMBINATOR_TYPE = 1; +Parser.MEDIA_FEATURE_TYPE = 2; +Parser.MEDIA_QUERY_TYPE = 3; +Parser.PROPERTY_NAME_TYPE = 4; +Parser.PROPERTY_VALUE_TYPE = 5; +Parser.PROPERTY_VALUE_PART_TYPE = 6; +Parser.SELECTOR_TYPE = 7; +Parser.SELECTOR_PART_TYPE = 8; +Parser.SELECTOR_SUB_PART_TYPE = 9; + +Parser.prototype = function(){ + + var proto = new EventTarget(), //new prototype + prop, + additions = { + constructor: Parser, + DEFAULT_TYPE : 0, + COMBINATOR_TYPE : 1, + MEDIA_FEATURE_TYPE : 2, + MEDIA_QUERY_TYPE : 3, + PROPERTY_NAME_TYPE : 4, + PROPERTY_VALUE_TYPE : 5, + PROPERTY_VALUE_PART_TYPE : 6, + SELECTOR_TYPE : 7, + SELECTOR_PART_TYPE : 8, + SELECTOR_SUB_PART_TYPE : 9, + + _stylesheet: function(){ + + var tokenStream = this._tokenStream, + charset = null, + count, + token, + tt; + + this.fire("startstylesheet"); + this._charset(); + + this._skipCruft(); + while (tokenStream.peek() == Tokens.IMPORT_SYM){ + this._import(); + this._skipCruft(); + } + while (tokenStream.peek() == Tokens.NAMESPACE_SYM){ + this._namespace(); + this._skipCruft(); + } + tt = tokenStream.peek(); + while(tt > Tokens.EOF){ + + try { + + switch(tt){ + case Tokens.MEDIA_SYM: + this._media(); + this._skipCruft(); + break; + case Tokens.PAGE_SYM: + this._page(); + this._skipCruft(); + break; + case Tokens.FONT_FACE_SYM: + this._font_face(); + this._skipCruft(); + break; + case Tokens.KEYFRAMES_SYM: + this._keyframes(); + this._skipCruft(); + break; + case Tokens.VIEWPORT_SYM: + this._viewport(); + this._skipCruft(); + break; + case Tokens.UNKNOWN_SYM: //unknown @ rule + tokenStream.get(); + if (!this.options.strict){ + this.fire({ + type: "error", + error: null, + message: "Unknown @ rule: " + tokenStream.LT(0).value + ".", + line: tokenStream.LT(0).startLine, + col: tokenStream.LT(0).startCol + }); + count=0; + while (tokenStream.advance([Tokens.LBRACE, Tokens.RBRACE]) == Tokens.LBRACE){ + count++; //keep track of nesting depth + } + + while(count){ + tokenStream.advance([Tokens.RBRACE]); + count--; + } + + } else { + throw new SyntaxError("Unknown @ rule.", tokenStream.LT(0).startLine, tokenStream.LT(0).startCol); + } + break; + case Tokens.S: + this._readWhitespace(); + break; + default: + if(!this._ruleset()){ + switch(tt){ + case Tokens.CHARSET_SYM: + token = tokenStream.LT(1); + this._charset(false); + throw new SyntaxError("@charset not allowed here.", token.startLine, token.startCol); + case Tokens.IMPORT_SYM: + token = tokenStream.LT(1); + this._import(false); + throw new SyntaxError("@import not allowed here.", token.startLine, token.startCol); + case Tokens.NAMESPACE_SYM: + token = tokenStream.LT(1); + this._namespace(false); + throw new SyntaxError("@namespace not allowed here.", token.startLine, token.startCol); + default: + tokenStream.get(); //get the last token + this._unexpectedToken(tokenStream.token()); + } + + } + } + } catch(ex) { + if (ex instanceof SyntaxError && !this.options.strict){ + this.fire({ + type: "error", + error: ex, + message: ex.message, + line: ex.line, + col: ex.col + }); + } else { + throw ex; + } + } + + tt = tokenStream.peek(); + } + + if (tt != Tokens.EOF){ + this._unexpectedToken(tokenStream.token()); + } + + this.fire("endstylesheet"); + }, + + _charset: function(emit){ + var tokenStream = this._tokenStream, + charset, + token, + line, + col; + + if (tokenStream.match(Tokens.CHARSET_SYM)){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this._readWhitespace(); + tokenStream.mustMatch(Tokens.STRING); + + token = tokenStream.token(); + charset = token.value; + + this._readWhitespace(); + tokenStream.mustMatch(Tokens.SEMICOLON); + + if (emit !== false){ + this.fire({ + type: "charset", + charset:charset, + line: line, + col: col + }); + } + } + }, + + _import: function(emit){ + + var tokenStream = this._tokenStream, + tt, + uri, + importToken, + mediaList = []; + tokenStream.mustMatch(Tokens.IMPORT_SYM); + importToken = tokenStream.token(); + this._readWhitespace(); + + tokenStream.mustMatch([Tokens.STRING, Tokens.URI]); + uri = tokenStream.token().value.replace(/^(?:url\()?["']?([^"']+?)["']?\)?$/, "$1"); + + this._readWhitespace(); + + mediaList = this._media_query_list(); + tokenStream.mustMatch(Tokens.SEMICOLON); + this._readWhitespace(); + + if (emit !== false){ + this.fire({ + type: "import", + uri: uri, + media: mediaList, + line: importToken.startLine, + col: importToken.startCol + }); + } + + }, + + _namespace: function(emit){ + + var tokenStream = this._tokenStream, + line, + col, + prefix, + uri; + tokenStream.mustMatch(Tokens.NAMESPACE_SYM); + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + this._readWhitespace(); + if (tokenStream.match(Tokens.IDENT)){ + prefix = tokenStream.token().value; + this._readWhitespace(); + } + + tokenStream.mustMatch([Tokens.STRING, Tokens.URI]); + uri = tokenStream.token().value.replace(/(?:url\()?["']([^"']+)["']\)?/, "$1"); + + this._readWhitespace(); + tokenStream.mustMatch(Tokens.SEMICOLON); + this._readWhitespace(); + + if (emit !== false){ + this.fire({ + type: "namespace", + prefix: prefix, + uri: uri, + line: line, + col: col + }); + } + + }, + + _media: function(){ + var tokenStream = this._tokenStream, + line, + col, + mediaList;// = []; + tokenStream.mustMatch(Tokens.MEDIA_SYM); + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this._readWhitespace(); + + mediaList = this._media_query_list(); + + tokenStream.mustMatch(Tokens.LBRACE); + this._readWhitespace(); + + this.fire({ + type: "startmedia", + media: mediaList, + line: line, + col: col + }); + + while(true) { + if (tokenStream.peek() == Tokens.PAGE_SYM){ + this._page(); + } else if (tokenStream.peek() == Tokens.FONT_FACE_SYM){ + this._font_face(); + } else if (tokenStream.peek() == Tokens.VIEWPORT_SYM){ + this._viewport(); + } else if (!this._ruleset()){ + break; + } + } + + tokenStream.mustMatch(Tokens.RBRACE); + this._readWhitespace(); + + this.fire({ + type: "endmedia", + media: mediaList, + line: line, + col: col + }); + }, + _media_query_list: function(){ + var tokenStream = this._tokenStream, + mediaList = []; + + + this._readWhitespace(); + + if (tokenStream.peek() == Tokens.IDENT || tokenStream.peek() == Tokens.LPAREN){ + mediaList.push(this._media_query()); + } + + while(tokenStream.match(Tokens.COMMA)){ + this._readWhitespace(); + mediaList.push(this._media_query()); + } + + return mediaList; + }, + _media_query: function(){ + var tokenStream = this._tokenStream, + type = null, + ident = null, + token = null, + expressions = []; + + if (tokenStream.match(Tokens.IDENT)){ + ident = tokenStream.token().value.toLowerCase(); + if (ident != "only" && ident != "not"){ + tokenStream.unget(); + ident = null; + } else { + token = tokenStream.token(); + } + } + + this._readWhitespace(); + + if (tokenStream.peek() == Tokens.IDENT){ + type = this._media_type(); + if (token === null){ + token = tokenStream.token(); + } + } else if (tokenStream.peek() == Tokens.LPAREN){ + if (token === null){ + token = tokenStream.LT(1); + } + expressions.push(this._media_expression()); + } + + if (type === null && expressions.length === 0){ + return null; + } else { + this._readWhitespace(); + while (tokenStream.match(Tokens.IDENT)){ + if (tokenStream.token().value.toLowerCase() != "and"){ + this._unexpectedToken(tokenStream.token()); + } + + this._readWhitespace(); + expressions.push(this._media_expression()); + } + } + + return new MediaQuery(ident, type, expressions, token.startLine, token.startCol); + }, + _media_type: function(){ + return this._media_feature(); + }, + _media_expression: function(){ + var tokenStream = this._tokenStream, + feature = null, + token, + expression = null; + + tokenStream.mustMatch(Tokens.LPAREN); + + feature = this._media_feature(); + this._readWhitespace(); + + if (tokenStream.match(Tokens.COLON)){ + this._readWhitespace(); + token = tokenStream.LT(1); + expression = this._expression(); + } + + tokenStream.mustMatch(Tokens.RPAREN); + this._readWhitespace(); + + return new MediaFeature(feature, (expression ? new SyntaxUnit(expression, token.startLine, token.startCol) : null)); + }, + _media_feature: function(){ + var tokenStream = this._tokenStream; + + tokenStream.mustMatch(Tokens.IDENT); + + return SyntaxUnit.fromToken(tokenStream.token()); + }, + _page: function(){ + var tokenStream = this._tokenStream, + line, + col, + identifier = null, + pseudoPage = null; + tokenStream.mustMatch(Tokens.PAGE_SYM); + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this._readWhitespace(); + + if (tokenStream.match(Tokens.IDENT)){ + identifier = tokenStream.token().value; + if (identifier.toLowerCase() === "auto"){ + this._unexpectedToken(tokenStream.token()); + } + } + if (tokenStream.peek() == Tokens.COLON){ + pseudoPage = this._pseudo_page(); + } + + this._readWhitespace(); + + this.fire({ + type: "startpage", + id: identifier, + pseudo: pseudoPage, + line: line, + col: col + }); + + this._readDeclarations(true, true); + + this.fire({ + type: "endpage", + id: identifier, + pseudo: pseudoPage, + line: line, + col: col + }); + + }, + _margin: function(){ + var tokenStream = this._tokenStream, + line, + col, + marginSym = this._margin_sym(); + + if (marginSym){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this.fire({ + type: "startpagemargin", + margin: marginSym, + line: line, + col: col + }); + + this._readDeclarations(true); + + this.fire({ + type: "endpagemargin", + margin: marginSym, + line: line, + col: col + }); + return true; + } else { + return false; + } + }, + _margin_sym: function(){ + + var tokenStream = this._tokenStream; + + if(tokenStream.match([Tokens.TOPLEFTCORNER_SYM, Tokens.TOPLEFT_SYM, + Tokens.TOPCENTER_SYM, Tokens.TOPRIGHT_SYM, Tokens.TOPRIGHTCORNER_SYM, + Tokens.BOTTOMLEFTCORNER_SYM, Tokens.BOTTOMLEFT_SYM, + Tokens.BOTTOMCENTER_SYM, Tokens.BOTTOMRIGHT_SYM, + Tokens.BOTTOMRIGHTCORNER_SYM, Tokens.LEFTTOP_SYM, + Tokens.LEFTMIDDLE_SYM, Tokens.LEFTBOTTOM_SYM, Tokens.RIGHTTOP_SYM, + Tokens.RIGHTMIDDLE_SYM, Tokens.RIGHTBOTTOM_SYM])) + { + return SyntaxUnit.fromToken(tokenStream.token()); + } else { + return null; + } + + }, + + _pseudo_page: function(){ + + var tokenStream = this._tokenStream; + + tokenStream.mustMatch(Tokens.COLON); + tokenStream.mustMatch(Tokens.IDENT); + + return tokenStream.token().value; + }, + + _font_face: function(){ + var tokenStream = this._tokenStream, + line, + col; + tokenStream.mustMatch(Tokens.FONT_FACE_SYM); + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this._readWhitespace(); + + this.fire({ + type: "startfontface", + line: line, + col: col + }); + + this._readDeclarations(true); + + this.fire({ + type: "endfontface", + line: line, + col: col + }); + }, + + _viewport: function(){ + var tokenStream = this._tokenStream, + line, + col; + + tokenStream.mustMatch(Tokens.VIEWPORT_SYM); + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + + this._readWhitespace(); + + this.fire({ + type: "startviewport", + line: line, + col: col + }); + + this._readDeclarations(true); + + this.fire({ + type: "endviewport", + line: line, + col: col + }); + + }, + + _operator: function(inFunction){ + + var tokenStream = this._tokenStream, + token = null; + + if (tokenStream.match([Tokens.SLASH, Tokens.COMMA]) || + (inFunction && tokenStream.match([Tokens.PLUS, Tokens.STAR, Tokens.MINUS]))){ + token = tokenStream.token(); + this._readWhitespace(); + } + return token ? PropertyValuePart.fromToken(token) : null; + + }, + + _combinator: function(){ + + var tokenStream = this._tokenStream, + value = null, + token; + + if(tokenStream.match([Tokens.PLUS, Tokens.GREATER, Tokens.TILDE])){ + token = tokenStream.token(); + value = new Combinator(token.value, token.startLine, token.startCol); + this._readWhitespace(); + } + + return value; + }, + + _unary_operator: function(){ + + var tokenStream = this._tokenStream; + + if (tokenStream.match([Tokens.MINUS, Tokens.PLUS])){ + return tokenStream.token().value; + } else { + return null; + } + }, + + _property: function(){ + + var tokenStream = this._tokenStream, + value = null, + hack = null, + tokenValue, + token, + line, + col; + if (tokenStream.peek() == Tokens.STAR && this.options.starHack){ + tokenStream.get(); + token = tokenStream.token(); + hack = token.value; + line = token.startLine; + col = token.startCol; + } + + if(tokenStream.match(Tokens.IDENT)){ + token = tokenStream.token(); + tokenValue = token.value; + if (tokenValue.charAt(0) == "_" && this.options.underscoreHack){ + hack = "_"; + tokenValue = tokenValue.substring(1); + } + + value = new PropertyName(tokenValue, hack, (line||token.startLine), (col||token.startCol)); + this._readWhitespace(); + } + + return value; + }, + _ruleset: function(){ + + var tokenStream = this._tokenStream, + tt, + selectors; + try { + selectors = this._selectors_group(); + } catch (ex){ + if (ex instanceof SyntaxError && !this.options.strict){ + this.fire({ + type: "error", + error: ex, + message: ex.message, + line: ex.line, + col: ex.col + }); + tt = tokenStream.advance([Tokens.RBRACE]); + if (tt == Tokens.RBRACE){ + } else { + throw ex; + } + + } else { + throw ex; + } + return true; + } + if (selectors){ + + this.fire({ + type: "startrule", + selectors: selectors, + line: selectors[0].line, + col: selectors[0].col + }); + + this._readDeclarations(true); + + this.fire({ + type: "endrule", + selectors: selectors, + line: selectors[0].line, + col: selectors[0].col + }); + + } + + return selectors; + + }, + _selectors_group: function(){ + var tokenStream = this._tokenStream, + selectors = [], + selector; + + selector = this._selector(); + if (selector !== null){ + + selectors.push(selector); + while(tokenStream.match(Tokens.COMMA)){ + this._readWhitespace(); + selector = this._selector(); + if (selector !== null){ + selectors.push(selector); + } else { + this._unexpectedToken(tokenStream.LT(1)); + } + } + } + + return selectors.length ? selectors : null; + }, + _selector: function(){ + + var tokenStream = this._tokenStream, + selector = [], + nextSelector = null, + combinator = null, + ws = null; + nextSelector = this._simple_selector_sequence(); + if (nextSelector === null){ + return null; + } + + selector.push(nextSelector); + + do { + combinator = this._combinator(); + + if (combinator !== null){ + selector.push(combinator); + nextSelector = this._simple_selector_sequence(); + if (nextSelector === null){ + this._unexpectedToken(tokenStream.LT(1)); + } else { + selector.push(nextSelector); + } + } else { + if (this._readWhitespace()){ + ws = new Combinator(tokenStream.token().value, tokenStream.token().startLine, tokenStream.token().startCol); + combinator = this._combinator(); + nextSelector = this._simple_selector_sequence(); + if (nextSelector === null){ + if (combinator !== null){ + this._unexpectedToken(tokenStream.LT(1)); + } + } else { + + if (combinator !== null){ + selector.push(combinator); + } else { + selector.push(ws); + } + + selector.push(nextSelector); + } + } else { + break; + } + + } + } while(true); + + return new Selector(selector, selector[0].line, selector[0].col); + }, + _simple_selector_sequence: function(){ + + var tokenStream = this._tokenStream, + elementName = null, + modifiers = [], + selectorText= "", + components = [ + function(){ + return tokenStream.match(Tokens.HASH) ? + new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) : + null; + }, + this._class, + this._attrib, + this._pseudo, + this._negation + ], + i = 0, + len = components.length, + component = null, + found = false, + line, + col; + line = tokenStream.LT(1).startLine; + col = tokenStream.LT(1).startCol; + + elementName = this._type_selector(); + if (!elementName){ + elementName = this._universal(); + } + + if (elementName !== null){ + selectorText += elementName; + } + + while(true){ + if (tokenStream.peek() === Tokens.S){ + break; + } + while(i < len && component === null){ + component = components[i++].call(this); + } + + if (component === null){ + if (selectorText === ""){ + return null; + } else { + break; + } + } else { + i = 0; + modifiers.push(component); + selectorText += component.toString(); + component = null; + } + } + + + return selectorText !== "" ? + new SelectorPart(elementName, modifiers, selectorText, line, col) : + null; + }, + _type_selector: function(){ + + var tokenStream = this._tokenStream, + ns = this._namespace_prefix(), + elementName = this._element_name(); + + if (!elementName){ + if (ns){ + tokenStream.unget(); + if (ns.length > 1){ + tokenStream.unget(); + } + } + + return null; + } else { + if (ns){ + elementName.text = ns + elementName.text; + elementName.col -= ns.length; + } + return elementName; + } + }, + _class: function(){ + + var tokenStream = this._tokenStream, + token; + + if (tokenStream.match(Tokens.DOT)){ + tokenStream.mustMatch(Tokens.IDENT); + token = tokenStream.token(); + return new SelectorSubPart("." + token.value, "class", token.startLine, token.startCol - 1); + } else { + return null; + } + + }, + _element_name: function(){ + + var tokenStream = this._tokenStream, + token; + + if (tokenStream.match(Tokens.IDENT)){ + token = tokenStream.token(); + return new SelectorSubPart(token.value, "elementName", token.startLine, token.startCol); + + } else { + return null; + } + }, + _namespace_prefix: function(){ + var tokenStream = this._tokenStream, + value = ""; + if (tokenStream.LA(1) === Tokens.PIPE || tokenStream.LA(2) === Tokens.PIPE){ + + if(tokenStream.match([Tokens.IDENT, Tokens.STAR])){ + value += tokenStream.token().value; + } + + tokenStream.mustMatch(Tokens.PIPE); + value += "|"; + + } + + return value.length ? value : null; + }, + _universal: function(){ + var tokenStream = this._tokenStream, + value = "", + ns; + + ns = this._namespace_prefix(); + if(ns){ + value += ns; + } + + if(tokenStream.match(Tokens.STAR)){ + value += "*"; + } + + return value.length ? value : null; + + }, + _attrib: function(){ + + var tokenStream = this._tokenStream, + value = null, + ns, + token; + + if (tokenStream.match(Tokens.LBRACKET)){ + token = tokenStream.token(); + value = token.value; + value += this._readWhitespace(); + + ns = this._namespace_prefix(); + + if (ns){ + value += ns; + } + + tokenStream.mustMatch(Tokens.IDENT); + value += tokenStream.token().value; + value += this._readWhitespace(); + + if(tokenStream.match([Tokens.PREFIXMATCH, Tokens.SUFFIXMATCH, Tokens.SUBSTRINGMATCH, + Tokens.EQUALS, Tokens.INCLUDES, Tokens.DASHMATCH])){ + + value += tokenStream.token().value; + value += this._readWhitespace(); + + tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]); + value += tokenStream.token().value; + value += this._readWhitespace(); + } + + tokenStream.mustMatch(Tokens.RBRACKET); + + return new SelectorSubPart(value + "]", "attribute", token.startLine, token.startCol); + } else { + return null; + } + }, + _pseudo: function(){ + + var tokenStream = this._tokenStream, + pseudo = null, + colons = ":", + line, + col; + + if (tokenStream.match(Tokens.COLON)){ + + if (tokenStream.match(Tokens.COLON)){ + colons += ":"; + } + + if (tokenStream.match(Tokens.IDENT)){ + pseudo = tokenStream.token().value; + line = tokenStream.token().startLine; + col = tokenStream.token().startCol - colons.length; + } else if (tokenStream.peek() == Tokens.FUNCTION){ + line = tokenStream.LT(1).startLine; + col = tokenStream.LT(1).startCol - colons.length; + pseudo = this._functional_pseudo(); + } + + if (pseudo){ + pseudo = new SelectorSubPart(colons + pseudo, "pseudo", line, col); + } + } + + return pseudo; + }, + _functional_pseudo: function(){ + + var tokenStream = this._tokenStream, + value = null; + + if(tokenStream.match(Tokens.FUNCTION)){ + value = tokenStream.token().value; + value += this._readWhitespace(); + value += this._expression(); + tokenStream.mustMatch(Tokens.RPAREN); + value += ")"; + } + + return value; + }, + _expression: function(){ + + var tokenStream = this._tokenStream, + value = ""; + + while(tokenStream.match([Tokens.PLUS, Tokens.MINUS, Tokens.DIMENSION, + Tokens.NUMBER, Tokens.STRING, Tokens.IDENT, Tokens.LENGTH, + Tokens.FREQ, Tokens.ANGLE, Tokens.TIME, + Tokens.RESOLUTION, Tokens.SLASH])){ + + value += tokenStream.token().value; + value += this._readWhitespace(); + } + + return value.length ? value : null; + + }, + _negation: function(){ + + var tokenStream = this._tokenStream, + line, + col, + value = "", + arg, + subpart = null; + + if (tokenStream.match(Tokens.NOT)){ + value = tokenStream.token().value; + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + value += this._readWhitespace(); + arg = this._negation_arg(); + value += arg; + value += this._readWhitespace(); + tokenStream.match(Tokens.RPAREN); + value += tokenStream.token().value; + + subpart = new SelectorSubPart(value, "not", line, col); + subpart.args.push(arg); + } + + return subpart; + }, + _negation_arg: function(){ + + var tokenStream = this._tokenStream, + args = [ + this._type_selector, + this._universal, + function(){ + return tokenStream.match(Tokens.HASH) ? + new SelectorSubPart(tokenStream.token().value, "id", tokenStream.token().startLine, tokenStream.token().startCol) : + null; + }, + this._class, + this._attrib, + this._pseudo + ], + arg = null, + i = 0, + len = args.length, + elementName, + line, + col, + part; + + line = tokenStream.LT(1).startLine; + col = tokenStream.LT(1).startCol; + + while(i < len && arg === null){ + + arg = args[i].call(this); + i++; + } + if (arg === null){ + this._unexpectedToken(tokenStream.LT(1)); + } + if (arg.type == "elementName"){ + part = new SelectorPart(arg, [], arg.toString(), line, col); + } else { + part = new SelectorPart(null, [arg], arg.toString(), line, col); + } + + return part; + }, + + _declaration: function(){ + + var tokenStream = this._tokenStream, + property = null, + expr = null, + prio = null, + error = null, + invalid = null, + propertyName= ""; + + property = this._property(); + if (property !== null){ + + tokenStream.mustMatch(Tokens.COLON); + this._readWhitespace(); + + expr = this._expr(); + if (!expr || expr.length === 0){ + this._unexpectedToken(tokenStream.LT(1)); + } + + prio = this._prio(); + propertyName = property.toString(); + if (this.options.starHack && property.hack == "*" || + this.options.underscoreHack && property.hack == "_") { + + propertyName = property.text; + } + + try { + this._validateProperty(propertyName, expr); + } catch (ex) { + invalid = ex; + } + + this.fire({ + type: "property", + property: property, + value: expr, + important: prio, + line: property.line, + col: property.col, + invalid: invalid + }); + + return true; + } else { + return false; + } + }, + + _prio: function(){ + + var tokenStream = this._tokenStream, + result = tokenStream.match(Tokens.IMPORTANT_SYM); + + this._readWhitespace(); + return result; + }, + + _expr: function(inFunction){ + + var tokenStream = this._tokenStream, + values = [], + value = null, + operator = null; + + value = this._term(inFunction); + if (value !== null){ + + values.push(value); + + do { + operator = this._operator(inFunction); + if (operator){ + values.push(operator); + } /*else { + values.push(new PropertyValue(valueParts, valueParts[0].line, valueParts[0].col)); + valueParts = []; + }*/ + + value = this._term(inFunction); + + if (value === null){ + break; + } else { + values.push(value); + } + } while(true); + } + + return values.length > 0 ? new PropertyValue(values, values[0].line, values[0].col) : null; + }, + + _term: function(inFunction){ + + var tokenStream = this._tokenStream, + unary = null, + value = null, + endChar = null, + token, + line, + col; + unary = this._unary_operator(); + if (unary !== null){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + } + if (tokenStream.peek() == Tokens.IE_FUNCTION && this.options.ieFilters){ + + value = this._ie_function(); + if (unary === null){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + } + } else if (inFunction && tokenStream.match([Tokens.LPAREN, Tokens.LBRACE, Tokens.LBRACKET])){ + + token = tokenStream.token(); + endChar = token.endChar; + value = token.value + this._expr(inFunction).text; + if (unary === null){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + } + tokenStream.mustMatch(Tokens.type(endChar)); + value += endChar; + this._readWhitespace(); + } else if (tokenStream.match([Tokens.NUMBER, Tokens.PERCENTAGE, Tokens.LENGTH, + Tokens.ANGLE, Tokens.TIME, + Tokens.FREQ, Tokens.STRING, Tokens.IDENT, Tokens.URI, Tokens.UNICODE_RANGE])){ + + value = tokenStream.token().value; + if (unary === null){ + line = tokenStream.token().startLine; + col = tokenStream.token().startCol; + } + this._readWhitespace(); + } else { + token = this._hexcolor(); + if (token === null){ + if (unary === null){ + line = tokenStream.LT(1).startLine; + col = tokenStream.LT(1).startCol; + } + if (value === null){ + if (tokenStream.LA(3) == Tokens.EQUALS && this.options.ieFilters){ + value = this._ie_function(); + } else { + value = this._function(); + } + } + + } else { + value = token.value; + if (unary === null){ + line = token.startLine; + col = token.startCol; + } + } + + } + + return value !== null ? + new PropertyValuePart(unary !== null ? unary + value : value, line, col) : + null; + + }, + + _function: function(){ + + var tokenStream = this._tokenStream, + functionText = null, + expr = null, + lt; + + if (tokenStream.match(Tokens.FUNCTION)){ + functionText = tokenStream.token().value; + this._readWhitespace(); + expr = this._expr(true); + functionText += expr; + if (this.options.ieFilters && tokenStream.peek() == Tokens.EQUALS){ + do { + + if (this._readWhitespace()){ + functionText += tokenStream.token().value; + } + if (tokenStream.LA(0) == Tokens.COMMA){ + functionText += tokenStream.token().value; + } + + tokenStream.match(Tokens.IDENT); + functionText += tokenStream.token().value; + + tokenStream.match(Tokens.EQUALS); + functionText += tokenStream.token().value; + lt = tokenStream.peek(); + while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){ + tokenStream.get(); + functionText += tokenStream.token().value; + lt = tokenStream.peek(); + } + } while(tokenStream.match([Tokens.COMMA, Tokens.S])); + } + + tokenStream.match(Tokens.RPAREN); + functionText += ")"; + this._readWhitespace(); + } + + return functionText; + }, + + _ie_function: function(){ + + var tokenStream = this._tokenStream, + functionText = null, + expr = null, + lt; + if (tokenStream.match([Tokens.IE_FUNCTION, Tokens.FUNCTION])){ + functionText = tokenStream.token().value; + + do { + + if (this._readWhitespace()){ + functionText += tokenStream.token().value; + } + if (tokenStream.LA(0) == Tokens.COMMA){ + functionText += tokenStream.token().value; + } + + tokenStream.match(Tokens.IDENT); + functionText += tokenStream.token().value; + + tokenStream.match(Tokens.EQUALS); + functionText += tokenStream.token().value; + lt = tokenStream.peek(); + while(lt != Tokens.COMMA && lt != Tokens.S && lt != Tokens.RPAREN){ + tokenStream.get(); + functionText += tokenStream.token().value; + lt = tokenStream.peek(); + } + } while(tokenStream.match([Tokens.COMMA, Tokens.S])); + + tokenStream.match(Tokens.RPAREN); + functionText += ")"; + this._readWhitespace(); + } + + return functionText; + }, + + _hexcolor: function(){ + + var tokenStream = this._tokenStream, + token = null, + color; + + if(tokenStream.match(Tokens.HASH)){ + + token = tokenStream.token(); + color = token.value; + if (!/#[a-f0-9]{3,6}/i.test(color)){ + throw new SyntaxError("Expected a hex color but found '" + color + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol); + } + this._readWhitespace(); + } + + return token; + }, + + _keyframes: function(){ + var tokenStream = this._tokenStream, + token, + tt, + name, + prefix = ""; + + tokenStream.mustMatch(Tokens.KEYFRAMES_SYM); + token = tokenStream.token(); + if (/^@\-([^\-]+)\-/.test(token.value)) { + prefix = RegExp.$1; + } + + this._readWhitespace(); + name = this._keyframe_name(); + + this._readWhitespace(); + tokenStream.mustMatch(Tokens.LBRACE); + + this.fire({ + type: "startkeyframes", + name: name, + prefix: prefix, + line: token.startLine, + col: token.startCol + }); + + this._readWhitespace(); + tt = tokenStream.peek(); + while(tt == Tokens.IDENT || tt == Tokens.PERCENTAGE) { + this._keyframe_rule(); + this._readWhitespace(); + tt = tokenStream.peek(); + } + + this.fire({ + type: "endkeyframes", + name: name, + prefix: prefix, + line: token.startLine, + col: token.startCol + }); + + this._readWhitespace(); + tokenStream.mustMatch(Tokens.RBRACE); + + }, + + _keyframe_name: function(){ + var tokenStream = this._tokenStream, + token; + + tokenStream.mustMatch([Tokens.IDENT, Tokens.STRING]); + return SyntaxUnit.fromToken(tokenStream.token()); + }, + + _keyframe_rule: function(){ + var tokenStream = this._tokenStream, + token, + keyList = this._key_list(); + + this.fire({ + type: "startkeyframerule", + keys: keyList, + line: keyList[0].line, + col: keyList[0].col + }); + + this._readDeclarations(true); + + this.fire({ + type: "endkeyframerule", + keys: keyList, + line: keyList[0].line, + col: keyList[0].col + }); + + }, + + _key_list: function(){ + var tokenStream = this._tokenStream, + token, + key, + keyList = []; + keyList.push(this._key()); + + this._readWhitespace(); + + while(tokenStream.match(Tokens.COMMA)){ + this._readWhitespace(); + keyList.push(this._key()); + this._readWhitespace(); + } + + return keyList; + }, + + _key: function(){ + + var tokenStream = this._tokenStream, + token; + + if (tokenStream.match(Tokens.PERCENTAGE)){ + return SyntaxUnit.fromToken(tokenStream.token()); + } else if (tokenStream.match(Tokens.IDENT)){ + token = tokenStream.token(); + + if (/from|to/i.test(token.value)){ + return SyntaxUnit.fromToken(token); + } + + tokenStream.unget(); + } + this._unexpectedToken(tokenStream.LT(1)); + }, + _skipCruft: function(){ + while(this._tokenStream.match([Tokens.S, Tokens.CDO, Tokens.CDC])){ + } + }, + _readDeclarations: function(checkStart, readMargins){ + var tokenStream = this._tokenStream, + tt; + + + this._readWhitespace(); + + if (checkStart){ + tokenStream.mustMatch(Tokens.LBRACE); + } + + this._readWhitespace(); + + try { + + while(true){ + + if (tokenStream.match(Tokens.SEMICOLON) || (readMargins && this._margin())){ + } else if (this._declaration()){ + if (!tokenStream.match(Tokens.SEMICOLON)){ + break; + } + } else { + break; + } + this._readWhitespace(); + } + + tokenStream.mustMatch(Tokens.RBRACE); + this._readWhitespace(); + + } catch (ex) { + if (ex instanceof SyntaxError && !this.options.strict){ + this.fire({ + type: "error", + error: ex, + message: ex.message, + line: ex.line, + col: ex.col + }); + tt = tokenStream.advance([Tokens.SEMICOLON, Tokens.RBRACE]); + if (tt == Tokens.SEMICOLON){ + this._readDeclarations(false, readMargins); + } else if (tt != Tokens.RBRACE){ + throw ex; + } + + } else { + throw ex; + } + } + + }, + _readWhitespace: function(){ + + var tokenStream = this._tokenStream, + ws = ""; + + while(tokenStream.match(Tokens.S)){ + ws += tokenStream.token().value; + } + + return ws; + }, + _unexpectedToken: function(token){ + throw new SyntaxError("Unexpected token '" + token.value + "' at line " + token.startLine + ", col " + token.startCol + ".", token.startLine, token.startCol); + }, + _verifyEnd: function(){ + if (this._tokenStream.LA(1) != Tokens.EOF){ + this._unexpectedToken(this._tokenStream.LT(1)); + } + }, + _validateProperty: function(property, value){ + Validation.validate(property, value); + }, + + parse: function(input){ + this._tokenStream = new TokenStream(input, Tokens); + this._stylesheet(); + }, + + parseStyleSheet: function(input){ + return this.parse(input); + }, + + parseMediaQuery: function(input){ + this._tokenStream = new TokenStream(input, Tokens); + var result = this._media_query(); + this._verifyEnd(); + return result; + }, + parsePropertyValue: function(input){ + + this._tokenStream = new TokenStream(input, Tokens); + this._readWhitespace(); + + var result = this._expr(); + this._readWhitespace(); + this._verifyEnd(); + return result; + }, + parseRule: function(input){ + this._tokenStream = new TokenStream(input, Tokens); + this._readWhitespace(); + + var result = this._ruleset(); + this._readWhitespace(); + this._verifyEnd(); + return result; + }, + parseSelector: function(input){ + + this._tokenStream = new TokenStream(input, Tokens); + this._readWhitespace(); + + var result = this._selector(); + this._readWhitespace(); + this._verifyEnd(); + return result; + }, + parseStyleAttribute: function(input){ + input += "}"; // for error recovery in _readDeclarations() + this._tokenStream = new TokenStream(input, Tokens); + this._readDeclarations(); + } + }; + for (prop in additions){ + if (additions.hasOwnProperty(prop)){ + proto[prop] = additions[prop]; + } + } + + return proto; +}(); +var Properties = { + "align-items" : "flex-start | flex-end | center | baseline | stretch", + "align-content" : "flex-start | flex-end | center | space-between | space-around | stretch", + "align-self" : "auto | flex-start | flex-end | center | baseline | stretch", + "-webkit-align-items" : "flex-start | flex-end | center | baseline | stretch", + "-webkit-align-content" : "flex-start | flex-end | center | space-between | space-around | stretch", + "-webkit-align-self" : "auto | flex-start | flex-end | center | baseline | stretch", + "alignment-adjust" : "auto | baseline | before-edge | text-before-edge | middle | central | after-edge | text-after-edge | ideographic | alphabetic | hanging | mathematical | | ", + "alignment-baseline" : "baseline | use-script | before-edge | text-before-edge | after-edge | text-after-edge | central | middle | ideographic | alphabetic | hanging | mathematical", + "animation" : 1, + "animation-delay" : { multi: "
diff --git a/modules/backend/behaviors/importexportcontroller/partials/_export_result_form.php b/modules/backend/behaviors/importexportcontroller/partials/_export_result_form.php new file mode 100644 index 0000000..81038ea --- /dev/null +++ b/modules/backend/behaviors/importexportcontroller/partials/_export_result_form.php @@ -0,0 +1,34 @@ +fatalError): ?> + + + + + + + + + + + + \ No newline at end of file diff --git a/modules/backend/behaviors/importexportcontroller/partials/_import_db_columns.php b/modules/backend/behaviors/importexportcontroller/partials/_import_db_columns.php new file mode 100644 index 0000000..256d8ee --- /dev/null +++ b/modules/backend/behaviors/importexportcontroller/partials/_import_db_columns.php @@ -0,0 +1,23 @@ +
+
    + $label): ?> + importIsColumnRequired($column); + $iconName = $isRequired ? 'icon-asterisk' : 'icon-link'; + ?> +
  • + + + + + +
  • + +
+
+ + \ No newline at end of file diff --git a/modules/backend/behaviors/importexportcontroller/partials/_import_file_columns.php b/modules/backend/behaviors/importexportcontroller/partials/_import_file_columns.php new file mode 100644 index 0000000..d64883c --- /dev/null +++ b/modules/backend/behaviors/importexportcontroller/partials/_import_file_columns.php @@ -0,0 +1,44 @@ +
+ +
    + $column): ?> +
  • +
    + + + + + + + + + +
    +
    +
      +
      +
    • + +
    + +

    + +

    + +
    + + diff --git a/modules/backend/behaviors/importexportcontroller/partials/_import_form.php b/modules/backend/behaviors/importexportcontroller/partials/_import_form.php new file mode 100644 index 0000000..daa43fe --- /dev/null +++ b/modules/backend/behaviors/importexportcontroller/partials/_import_form.php @@ -0,0 +1,50 @@ +
    + fatalError): ?> + + 'importForm']) ?> + + +
    + +
    + + + + + + + + + + + +
    diff --git a/modules/backend/behaviors/importexportcontroller/partials/_import_result_form.php b/modules/backend/behaviors/importexportcontroller/partials/_import_result_form.php new file mode 100644 index 0000000..b559361 --- /dev/null +++ b/modules/backend/behaviors/importexportcontroller/partials/_import_result_form.php @@ -0,0 +1,107 @@ +fatalError): ?> + + + + + + + + + + diff --git a/modules/backend/behaviors/importexportcontroller/partials/_import_toolbar.php b/modules/backend/behaviors/importexportcontroller/partials/_import_toolbar.php new file mode 100644 index 0000000..db503c4 --- /dev/null +++ b/modules/backend/behaviors/importexportcontroller/partials/_import_toolbar.php @@ -0,0 +1,16 @@ + diff --git a/modules/backend/behaviors/importexportcontroller/partials/fields_export.yaml b/modules/backend/behaviors/importexportcontroller/partials/fields_export.yaml new file mode 100644 index 0000000..b6582bb --- /dev/null +++ b/modules/backend/behaviors/importexportcontroller/partials/fields_export.yaml @@ -0,0 +1,58 @@ +# =================================== +# Field Definitions +# =================================== + +fields: + step1_section: + label: backend::lang.import_export.export_output_format + type: section + + format_preset: + label: backend::lang.import_export.file_format + type: dropdown + default: standard + options: + standard: backend::lang.import_export.standard_format + custom: backend::lang.import_export.custom_format + span: left + + format_delimiter: + label: backend::lang.import_export.delimiter_char + default: ',' + span: left + trigger: + action: show + condition: value[custom] + field: format_preset + + format_enclosure: + label: backend::lang.import_export.enclosure_char + span: auto + default: '"' + trigger: + action: show + condition: value[custom] + field: format_preset + + format_escape: + label: backend::lang.import_export.escape_char + span: auto + default: '\' + trigger: + action: show + condition: value[custom] + field: format_preset + + step2_section: + label: backend::lang.import_export.select_columns + type: section + + export_columns: + label: backend::lang.import_export.columns + type: partial + path: ~/modules/backend/behaviors/importexportcontroller/partials/_export_columns.php + span: left + + step3_section: + label: backend::lang.import_export.set_export_options + type: section diff --git a/modules/backend/behaviors/importexportcontroller/partials/fields_import.yaml b/modules/backend/behaviors/importexportcontroller/partials/fields_import.yaml new file mode 100644 index 0000000..139a368 --- /dev/null +++ b/modules/backend/behaviors/importexportcontroller/partials/fields_import.yaml @@ -0,0 +1,95 @@ +# =================================== +# Field Definitions +# =================================== + +fields: + step1_section: + label: backend::lang.import_export.upload_csv_file + type: section + + import_file: + label: backend::lang.import_export.import_file + type: fileupload + mode: file + span: left + fileTypes: csv + useCaption: false + + format_preset: + label: backend::lang.import_export.file_format + type: dropdown + default: standard + options: + standard: backend::lang.import_export.standard_format + custom: backend::lang.import_export.custom_format + span: right + + format_delimiter: + label: backend::lang.import_export.delimiter_char + default: ',' + span: left + trigger: + action: show + condition: value[custom] + field: format_preset + + format_enclosure: + label: backend::lang.import_export.enclosure_char + span: auto + default: '"' + trigger: + action: show + condition: value[custom] + field: format_preset + + format_escape: + label: backend::lang.import_export.escape_char + span: auto + default: '\' + trigger: + action: show + condition: value[custom] + field: format_preset + + format_encoding: + label: backend::lang.import_export.encoding_format + span: auto + default: UTF-8 + type: dropdown + trigger: + action: show + condition: value[custom] + field: format_preset + + first_row_titles: + label: backend::lang.import_export.first_row_contains_titles + comment: backend::lang.import_export.first_row_contains_titles_desc + type: checkbox + default: true + span: left + + step2_section: + label: backend::lang.import_export.match_columns + type: section + + column_control_panel: + type: partial + path: ~/modules/backend/behaviors/importexportcontroller/partials/_import_toolbar.php + + import_file_columns: + label: backend::lang.import_export.file_columns + type: partial + path: ~/modules/backend/behaviors/importexportcontroller/partials/_import_file_columns.php + dependsOn: [import_file, first_row_titles, format_delimiter, format_enclosure, format_escape, format_encoding] + span: left + + import_db_columns: + label: backend::lang.import_export.database_fields + type: partial + path: ~/modules/backend/behaviors/importexportcontroller/partials/_import_db_columns.php + dependsOn: [import_file, first_row_titles, format_delimiter, format_enclosure, format_escape, format_encoding] + span: right + + step3_section: + label: backend::lang.import_export.set_import_options + type: section \ No newline at end of file diff --git a/modules/backend/behaviors/importexportcontroller/views/export.php b/modules/backend/behaviors/importexportcontroller/views/export.php new file mode 100644 index 0000000..6c0be77 --- /dev/null +++ b/modules/backend/behaviors/importexportcontroller/views/export.php @@ -0,0 +1,24 @@ + + makeLayoutPartial('breadcrumb') ?> + + + 'layout']) ?> + +
    + exportRender() ?> +
    + +
    +
    + +
    +
    + + diff --git a/modules/backend/behaviors/importexportcontroller/views/import.php b/modules/backend/behaviors/importexportcontroller/views/import.php new file mode 100644 index 0000000..f40d5b8 --- /dev/null +++ b/modules/backend/behaviors/importexportcontroller/views/import.php @@ -0,0 +1,24 @@ + + makeLayoutPartial('breadcrumb') ?> + + + 'layout']) ?> + +
    + importRender() ?> +
    + +
    +
    + +
    +
    + + diff --git a/modules/backend/behaviors/listcontroller/partials/_container.php b/modules/backend/behaviors/listcontroller/partials/_container.php new file mode 100644 index 0000000..037ba06 --- /dev/null +++ b/modules/backend/behaviors/listcontroller/partials/_container.php @@ -0,0 +1,9 @@ + + render() ?> + + + + render() ?> + + +render() ?> diff --git a/modules/backend/behaviors/listcontroller/views/_list_toolbar.php b/modules/backend/behaviors/listcontroller/views/_list_toolbar.php new file mode 100644 index 0000000..f1dbb6f --- /dev/null +++ b/modules/backend/behaviors/listcontroller/views/_list_toolbar.php @@ -0,0 +1,59 @@ +getClassExtension(\Backend\Behaviors\ListController::class); +$listConfig = $listController->getConfig(); +?> + +
    + isClassExtendedWith(\Backend\Behaviors\FormController::class)): ?> + + trans(\Winter\Storm\Support\Str::before($listConfig->title, '_plural'))])); ?> + + + + showCheckboxes) && $listConfig->showCheckboxes != false): ?> + + + + isClassExtendedWith(\Backend\Behaviors\ReorderController::class)): ?> + + trans($listConfig->title)])); ?> + + + + isClassExtendedWith(\Backend\Behaviors\ImportExportController::class)): ?> +
    + asExtension(\Backend\Behaviors\ImportExportController::class); ?> + userHasAccess('export')): ?> + + + + + userHasAccess('import')): ?> + + + + +
    + +
    diff --git a/modules/backend/behaviors/listcontroller/views/index.php b/modules/backend/behaviors/listcontroller/views/index.php new file mode 100644 index 0000000..ea43a36 --- /dev/null +++ b/modules/backend/behaviors/listcontroller/views/index.php @@ -0,0 +1 @@ +listRender() ?> diff --git a/modules/backend/behaviors/relationcontroller/assets/css/relation.css b/modules/backend/behaviors/relationcontroller/assets/css/relation.css new file mode 100644 index 0000000..ad68855 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/assets/css/relation.css @@ -0,0 +1,39 @@ +.relation-behavior { + margin-bottom: 20px; +} +.relation-behavior .control-list { + border: 1px solid #eeeeee; +} +.relation-behavior .control-list thead > tr > th { + border-top: none !important; + border-color: #eeeeee; +} +.relation-behavior .control-toolbar { + padding: 0 20px 20px 20px; +} +.relation-behavior .control-toolbar .toolbar-item .form-control.search { + padding-top: 5px; + padding-bottom: 5px; +} +.relation-behavior .control-toolbar .loading-indicator-container.size-input-text { + min-height: 0; +} +.relation-behavior .control-toolbar .loading-indicator-container.size-input-text .loading-indicator > span { + top: 4px; +} +.relation-behavior .list-header { + padding: 0; +} +.relation-behavior .control-list:last-child > table { + margin-bottom: 0; +} +.relation-flush .control-list { + border-top: none; +} +.relation-inset { + margin-left: -20px; + margin-right: -20px; +} +.form-group > .relation-behavior .control-toolbar { + padding: 0 0 10px 0; +} diff --git a/modules/backend/behaviors/relationcontroller/assets/js/winter.relation.js b/modules/backend/behaviors/relationcontroller/assets/js/winter.relation.js new file mode 100644 index 0000000..5af54eb --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/assets/js/winter.relation.js @@ -0,0 +1,100 @@ +/* + * Scripts for the Relation controller behavior. + */ ++function ($) { "use strict"; + + var RelationBehavior = function() { + + this.toggleListCheckbox = function(el) { + $(el).closest('.control-list').listWidget('toggleChecked', [el]) + } + + this.clickViewListRecord = function(recordId, relationId, sessionKey) { + var newPopup = $(''), + $container = $('#'+relationId), + requestData = paramToObj('data-request-data', $container.data('request-data')) + + newPopup.popup({ + handler: 'onRelationClickViewList', + size: 'huge', + extraData: $.extend({}, requestData, { + 'manage_id': recordId, + '_session_key': sessionKey + }) + }) + } + + this.clickManageListRecord = function(recordId, relationId, sessionKey) { + var oldPopup = $('#relationManagePopup'), + $container = $('#'+relationId), + requestData = paramToObj('data-request-data', $container.data('request-data')) + + $.request('onRelationClickManageList', { + data: $.extend({}, requestData, { + 'record_id': recordId, + '_session_key': sessionKey + }) + }) + + oldPopup.popup('hide') + } + + this.clickManagePivotListRecord = function(foreignId, relationId, sessionKey) { + var oldPopup = $('#relationManagePivotPopup'), + newPopup = $(''), + $container = $('#'+relationId), + requestData = paramToObj('data-request-data', $container.data('request-data')) + + if (oldPopup.length) { + oldPopup.popup('hide') + } + + newPopup.popup({ + handler: 'onRelationClickManageListPivot', + size: 'huge', + extraData: $.extend({}, requestData, { + 'foreign_id': foreignId, + '_session_key': sessionKey + }) + }) + } + + /* + * This function is called every time a record is created, added, removed + * or deleted using the relation widget. It triggers the change.oc.formwidget + * event to notify other elements on the page about the changed form state. + */ + this.changed = function(relationId, event) { + $('[data-field-name="' + relationId + '"]').trigger('change.oc.formwidget', {event: event}); + } + + /* + * This function transfers the supplied variables as hidden form inputs, + * to any popup that is spawned within the supplied container. The spawned + * popup must contain a form element. + */ + this.bindToPopups = function(container, vars) { + $(container).on('show.oc.popup', function(event, $trigger, $modal){ + var $form = $('form', $modal) + $.each(vars, function(name, value){ + $form.prepend($('').attr({ type: 'hidden', name: name, value: value })) + }) + }) + } + + function paramToObj(name, value) { + if (value === undefined) value = '' + if (typeof value == 'object') return value + + try { + return ocJSON("{" + value + "}") + } + catch (e) { + throw new Error('Error parsing the '+name+' attribute value. '+e) + } + } + + } + + $.wn.relationBehavior = new RelationBehavior; +}(window.jQuery); diff --git a/modules/backend/behaviors/relationcontroller/assets/less/relation.less b/modules/backend/behaviors/relationcontroller/assets/less/relation.less new file mode 100644 index 0000000..a6731fa --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/assets/less/relation.less @@ -0,0 +1,60 @@ +@import "../../../../assets/less/core/boot.less"; + +@color-relation-border: #eeeeee; + +.relation-behavior { + margin-bottom: 20px; + + .control-list { + border: 1px solid @color-relation-border; + + thead > tr > th { + border-top: none !important; + border-color: @color-relation-border; + } + } + + .control-toolbar { + padding: 0 20px 20px 20px; + + .toolbar-item .form-control.search { + padding-top: 5px; + padding-bottom: 5px; + } + + .loading-indicator-container.size-input-text { + min-height: 0; + .loading-indicator > span { + top: 4px; + } + } + } + + .list-header { + padding: 0; + } + + .control-list:last-child > table { + margin-bottom: 0; + } +} + +// Relation manager to sit flush to the element above +.relation-flush { + .control-list { + border-top: none; + } +} + +// Relation manager to sit inset the standard padding (20px) +.relation-inset { + margin-left: -20px; + margin-right: -20px; +} + +// Displayed in a form field +.form-group > .relation-behavior { + .control-toolbar { + padding: 0 0 10px 0; + } +} \ No newline at end of file diff --git a/modules/backend/behaviors/relationcontroller/partials/_button_add.php b/modules/backend/behaviors/relationcontroller/partials/_button_add.php new file mode 100644 index 0000000..08da269 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_button_add.php @@ -0,0 +1,8 @@ + + trans($relationLabel)])) ?> + diff --git a/modules/backend/behaviors/relationcontroller/partials/_button_create.php b/modules/backend/behaviors/relationcontroller/partials/_button_create.php new file mode 100644 index 0000000..b2080b1 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_button_create.php @@ -0,0 +1,8 @@ + + trans($relationLabel)])) ?> + diff --git a/modules/backend/behaviors/relationcontroller/partials/_button_delete.php b/modules/backend/behaviors/relationcontroller/partials/_button_delete.php new file mode 100644 index 0000000..d8df34c --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_button_delete.php @@ -0,0 +1,26 @@ + + + + + diff --git a/modules/backend/behaviors/relationcontroller/partials/_button_link.php b/modules/backend/behaviors/relationcontroller/partials/_button_link.php new file mode 100644 index 0000000..6e1c3d5 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_button_link.php @@ -0,0 +1,8 @@ + + trans($relationLabel)])) ?> + diff --git a/modules/backend/behaviors/relationcontroller/partials/_button_refresh.php b/modules/backend/behaviors/relationcontroller/partials/_button_refresh.php new file mode 100644 index 0000000..993533f --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_button_refresh.php @@ -0,0 +1,6 @@ + diff --git a/modules/backend/behaviors/relationcontroller/partials/_button_remove.php b/modules/backend/behaviors/relationcontroller/partials/_button_remove.php new file mode 100644 index 0000000..a5326e4 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_button_remove.php @@ -0,0 +1,24 @@ + + + + + diff --git a/modules/backend/behaviors/relationcontroller/partials/_button_unlink.php b/modules/backend/behaviors/relationcontroller/partials/_button_unlink.php new file mode 100644 index 0000000..59ea3ec --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_button_unlink.php @@ -0,0 +1,9 @@ + + + diff --git a/modules/backend/behaviors/relationcontroller/partials/_button_update.php b/modules/backend/behaviors/relationcontroller/partials/_button_update.php new file mode 100644 index 0000000..efadc67 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_button_update.php @@ -0,0 +1,9 @@ + + trans($relationLabel)])) ?> + diff --git a/modules/backend/behaviors/relationcontroller/partials/_container.php b/modules/backend/behaviors/relationcontroller/partials/_container.php new file mode 100644 index 0000000..eb66e96 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_container.php @@ -0,0 +1,18 @@ +
    + + relationRenderToolbar()): ?> + +
    + +
    + + + +
    + relationRenderView() ?> +
    + +
    diff --git a/modules/backend/behaviors/relationcontroller/partials/_manage_form.php b/modules/backend/behaviors/relationcontroller/partials/_manage_form.php new file mode 100644 index 0000000..cab9fec --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_manage_form.php @@ -0,0 +1,71 @@ +
    + + + true, + 'sessionKey' => $newSessionKey, + 'data-request-success' => "$.wn.relationBehavior.changed('" . e($relationField) . "', 'updated')", + ]) ?> + + + + + + + + + + + + + + + + + + true, + 'data-request-success' => "$.wn.relationBehavior.changed('" . e($relationField) . "', 'created')", + 'sessionKey' => $newSessionKey + ]) ?> + + + + + + + + + + + + + +
    + + diff --git a/modules/backend/behaviors/relationcontroller/partials/_manage_form_footer_create.php b/modules/backend/behaviors/relationcontroller/partials/_manage_form_footer_create.php new file mode 100644 index 0000000..4a61261 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_manage_form_footer_create.php @@ -0,0 +1,11 @@ + + diff --git a/modules/backend/behaviors/relationcontroller/partials/_manage_form_footer_update.php b/modules/backend/behaviors/relationcontroller/partials/_manage_form_footer_update.php new file mode 100644 index 0000000..a965490 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_manage_form_footer_update.php @@ -0,0 +1,20 @@ +readOnly): ?> + + + + + diff --git a/modules/backend/behaviors/relationcontroller/partials/_manage_list.php b/modules/backend/behaviors/relationcontroller/partials/_manage_list.php new file mode 100644 index 0000000..f3664c9 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_manage_list.php @@ -0,0 +1,24 @@ +
    + + + +
    + + render() ?> + + + render() ?> + + render() ?> +
    + + + +
    diff --git a/modules/backend/behaviors/relationcontroller/partials/_manage_list_footer.php b/modules/backend/behaviors/relationcontroller/partials/_manage_list_footer.php new file mode 100644 index 0000000..a2ddafa --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_manage_list_footer.php @@ -0,0 +1,17 @@ +showCheckboxes): ?> + + + diff --git a/modules/backend/behaviors/relationcontroller/partials/_manage_pivot.php b/modules/backend/behaviors/relationcontroller/partials/_manage_pivot.php new file mode 100644 index 0000000..6ac2419 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_manage_pivot.php @@ -0,0 +1,32 @@ +
    + + + + + +
    + + render() ?> + + + render() ?> + + render() ?> +
    + + + +
    + diff --git a/modules/backend/behaviors/relationcontroller/partials/_manage_pivot_footer.php b/modules/backend/behaviors/relationcontroller/partials/_manage_pivot_footer.php new file mode 100644 index 0000000..4402932 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_manage_pivot_footer.php @@ -0,0 +1,18 @@ +showCheckboxes): ?> + + + diff --git a/modules/backend/behaviors/relationcontroller/partials/_pivot_form.php b/modules/backend/behaviors/relationcontroller/partials/_pivot_form.php new file mode 100644 index 0000000..f93cbd7 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_pivot_form.php @@ -0,0 +1,53 @@ + + + ['_relation_field' => $relationField, 'manage_id' => $relationManageId], + 'data-request-success' => "$.wn.relationBehavior.changed('" . e($relationField) . "', 'updated')", + 'data-popup-load-indicator' => true + ]) ?> + + + + + + + + + + ['_relation_field' => $relationField, 'foreign_id' => $foreignId], + 'data-request-success' => "$.wn.relationBehavior.changed('" . e($relationField) . "', 'created')", + 'data-popup-load-indicator' => true + ]) ?> + + + + + + + + diff --git a/modules/backend/behaviors/relationcontroller/partials/_pivot_form_footer.php b/modules/backend/behaviors/relationcontroller/partials/_pivot_form_footer.php new file mode 100644 index 0000000..a965490 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_pivot_form_footer.php @@ -0,0 +1,20 @@ +readOnly): ?> + + + + + diff --git a/modules/backend/behaviors/relationcontroller/partials/_toolbar.php b/modules/backend/behaviors/relationcontroller/partials/_toolbar.php new file mode 100644 index 0000000..d7f85f5 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_toolbar.php @@ -0,0 +1,18 @@ +
    + + $text): ?> + + + relationMakePartial('button_update', [ + 'relationManageId' => $relationViewModel->getKey(), + 'text' => $text + ]) ?> + + relationMakePartial('button_' . $type, [ + 'text' => $text + ]) ?> + + + + +
    diff --git a/modules/backend/behaviors/relationcontroller/partials/_view.php b/modules/backend/behaviors/relationcontroller/partials/_view.php new file mode 100644 index 0000000..2b14e43 --- /dev/null +++ b/modules/backend/behaviors/relationcontroller/partials/_view.php @@ -0,0 +1,5 @@ + + render() ?> + + +render() ?> diff --git a/modules/backend/behaviors/reordercontroller/assets/js/winter.reorder.js b/modules/backend/behaviors/reordercontroller/assets/js/winter.reorder.js new file mode 100644 index 0000000..de31c2a --- /dev/null +++ b/modules/backend/behaviors/reordercontroller/assets/js/winter.reorder.js @@ -0,0 +1,82 @@ +/* + * Scripts for the Reorder controller behavior. + * + * The following functions are observed: + * - Simple sorting: Post back the original sort orders and the new ordered identifiers. + * - Nested sorting: Post back source and target nodes IDs and the move positioning. + */ ++function ($) { "use strict"; + + var ReorderBehavior = function() { + + this.sortMode = null + + this.simpleSortOrders = [] + + this.initSorting = function (mode) { + this.sortMode = mode + + if (mode == 'simple') { + this.initSortingSimple() + } + + $('#reorderTreeList').on('move.oc.treelist', $.proxy(this.processReorder, this)) + } + + + this.processReorder = function(ev, sortData){ + var postData + + if (this.sortMode == 'simple') { + postData = { sort_orders: this.simpleSortOrders } + } + else if (this.sortMode == 'nested') { + postData = this.getNestedMoveData(sortData) + } + + $('#reorderTreeList').request('onReorder', { + data: postData + }) + } + + this.getNestedMoveData = function (sortData) { + var + $el, + $item = sortData.item, + moveData = { + targetNode: 0, + sourceNode: $item.data('recordId'), + position: 'root' + } + + if (($el = $item.next()) && $el.length) { + moveData.position = 'before' + } + else if (($el = $item.prev()) && $el.length) { + moveData.position = 'after' + } + else if (($el = $item.parents('li:first')) && $el.length) { + moveData.position = 'child' + } + + if ($el.length) { + moveData.targetNode = $el.data('recordId') + } + + return moveData + } + + this.initSortingSimple = function () { + var sortOrders = [] + + $('#reorderTreeList li').each(function(i) { + sortOrders.push(i); + }) + + this.simpleSortOrders = sortOrders + } + + } + + $.wn.reorderBehavior = new ReorderBehavior; +}(window.jQuery); diff --git a/modules/backend/behaviors/reordercontroller/partials/_container.php b/modules/backend/behaviors/reordercontroller/partials/_container.php new file mode 100644 index 0000000..7a28c31 --- /dev/null +++ b/modules/backend/behaviors/reordercontroller/partials/_container.php @@ -0,0 +1,29 @@ + + +
    + render() ?> +
    + + + + +
    + data-handle=" li > .record > a.move' ?>" + data-stripe-load-indicator> + +
      + reorderMakePartial('records', ['records' => $reorderRecords]) ?> +
    + +

    + +
    + + + diff --git a/modules/backend/behaviors/reordercontroller/partials/_records.php b/modules/backend/behaviors/reordercontroller/partials/_records.php new file mode 100644 index 0000000..15100c3 --- /dev/null +++ b/modules/backend/behaviors/reordercontroller/partials/_records.php @@ -0,0 +1,23 @@ + + +
  • + data-record-sort-order="{$record->getSortOrderColumn()} ?>" + + > +
    + + reorderGetRecordName($record)) ?> + +
    + + +
      + children): ?> + reorderMakePartial('records', ['records' => $record->children]) ?> + +
    + +
  • + + diff --git a/modules/backend/behaviors/reordercontroller/views/_reorder_toolbar.php b/modules/backend/behaviors/reordercontroller/views/_reorder_toolbar.php new file mode 100644 index 0000000..6320a60 --- /dev/null +++ b/modules/backend/behaviors/reordercontroller/views/_reorder_toolbar.php @@ -0,0 +1,5 @@ + diff --git a/modules/backend/behaviors/reordercontroller/views/reorder.php b/modules/backend/behaviors/reordercontroller/views/reorder.php new file mode 100644 index 0000000..fc56b60 --- /dev/null +++ b/modules/backend/behaviors/reordercontroller/views/reorder.php @@ -0,0 +1,5 @@ + + makeLayoutPartial('breadcrumb') ?> + + +reorderRender() ?> diff --git a/modules/backend/classes/AuthManager.php b/modules/backend/classes/AuthManager.php new file mode 100644 index 0000000..deb56cc --- /dev/null +++ b/modules/backend/classes/AuthManager.php @@ -0,0 +1,289 @@ + null, + 'label' => null, + 'comment' => null, + 'roles' => null, + 'order' => 500 + ]; + + /** + * @var array Cache of registration callbacks. + */ + protected $callbacks = []; + + /** + * @var array List of registered permissions. + */ + protected $permissions = []; + + /** + * @var array List of owner aliases. ['Aliased.Owner' => 'Real.Owner'] + */ + protected $aliases = []; + + /** + * @var array List of registered permission roles. + */ + protected $permissionRoles = false; + + /** + * @var array Cache of registered permissions. + */ + protected $permissionCache = false; + + protected function init() + { + $this->useThrottle = Config::get('auth.throttle.enabled', true); + parent::init(); + } + + /** + * Registers a callback function that defines authentication permissions. + * The callback function should register permissions by calling the manager's + * registerPermissions() function. The manager instance is passed to the + * callback function as an argument. Usage: + * + * BackendAuth::registerCallback(function ($manager) { + * $manager->registerPermissions([...]); + * }); + * + * @param callable $callback A callable function. + */ + public function registerCallback(callable $callback) + { + $this->callbacks[] = $callback; + } + + /** + * Registers the back-end permission items. + * The argument is an array of the permissions. The array keys represent the + * permission codes, specific for the plugin/module. Each element in the + * array should be an associative array with the following keys: + * - label - specifies the menu label localization string key, required. + * - order - a position of the item in the menu, optional. + * - comment - a brief comment that describes the permission, optional. + * - tab - assign this permission to a tabbed group, optional. + * @param string $owner Specifies the permissions' owner plugin or module in the format Author.Plugin + * @param array $definitions An array of the menu item definitions. + */ + public function registerPermissions($owner, array $definitions) + { + // Resolve alias + $owner = $this->aliases[$owner] ?? $owner; + + foreach ($definitions as $code => $definition) { + $permission = (object) array_merge(self::$permissionDefaults, array_merge($definition, [ + 'code' => $code, + 'owner' => $owner + ])); + + $this->permissions[] = $permission; + } + + // Clear the permission cache + $this->permissionCache = false; + } + + /** + * Register a permission owner alias + * + * @param string $owner The owner to register an alias for. Example: Real.Owner + * @param string $alias The alias to register. Example: Aliased.Owner + * @return void + */ + public function registerPermissionOwnerAlias(string $owner, string $alias) + { + $this->aliases[$alias] = $owner; + } + + /** + * Removes a single back-end permission + * @param string $owner Specifies the permissions' owner plugin or module in the format Author.Plugin + * @param string $code The code of the permission to remove + * @return void + */ + public function removePermission($owner, $code) + { + if (!$this->permissions) { + throw new SystemException('Unable to remove permissions before they are loaded.'); + } + + // Resolve alias + $owner = $this->aliases[$owner] ?? $owner; + + $ownerPermissions = array_filter($this->permissions, function ($permission) use ($owner) { + return $permission->owner === $owner; + }); + + foreach ($ownerPermissions as $key => $permission) { + if ($permission->code === $code) { + unset($this->permissions[$key]); + } + } + + // Clear the permission cache + $this->permissionCache = false; + } + + /** + * Returns a list of the registered permissions items. + * @return array + */ + public function listPermissions() + { + if ($this->permissionCache !== false) { + return $this->permissionCache; + } + + /* + * Load module items + */ + foreach ($this->callbacks as $callback) { + $callback($this); + } + + /* + * Load plugin items + */ + $plugins = PluginManager::instance()->getPlugins(); + + foreach ($plugins as $id => $plugin) { + $items = $plugin->registerPermissions(); + if (!is_array($items)) { + continue; + } + + $this->registerPermissions($id, $items); + } + + /* + * Sort permission items + */ + usort($this->permissions, function ($a, $b) { + if ($a->order == $b->order) { + return 0; + } + + return $a->order > $b->order ? 1 : -1; + }); + + return $this->permissionCache = $this->permissions; + } + + /** + * Returns an array of registered permissions, grouped by tabs. + * @return array + */ + public function listTabbedPermissions() + { + $tabs = []; + + foreach ($this->listPermissions() as $permission) { + $tab = $permission->tab ?? 'backend::lang.form.undefined_tab'; + + if (!array_key_exists($tab, $tabs)) { + $tabs[$tab] = []; + } + + $tabs[$tab][] = $permission; + } + + return $tabs; + } + + /** + * {@inheritdoc} + */ + protected function createUserModelQuery() + { + return parent::createUserModelQuery()->withTrashed(); + } + + + /** + * {@inheritdoc} + */ + protected function validateUserModel($user) + { + if ( ! $user instanceof $this->userModel) { + return false; + } + + // Perform the deleted_at check manually since the relevant migrations + // might not have been run yet during the update to build 444. + // @see https://github.com/octobercms/october/issues/3999 + if (array_key_exists('deleted_at', $user->getAttributes()) && $user->deleted_at !== null) { + return false; + } + + return $user; + } + + /** + * Returns an array of registered permissions belonging to a given role code + * @param string $role + * @param bool $includeOrphans Include any permissons that do not have a default role specified + * @return array + */ + public function listPermissionsForRole($role, $includeOrphans = true) + { + if ($this->permissionRoles === false) { + $this->permissionRoles = []; + + foreach ($this->listPermissions() as $permission) { + if ($permission->roles) { + foreach ((array) $permission->roles as $_role) { + $this->permissionRoles[$_role][$permission->code] = 1; + } + } + else { + $this->permissionRoles['*'][$permission->code] = 1; + } + } + } + + $result = $this->permissionRoles[$role] ?? []; + + if ($includeOrphans) { + $result += $this->permissionRoles['*'] ?? []; + } + + return $result; + } + + public function hasPermissionsForRole($role) + { + return !!$this->listPermissionsForRole($role, false); + } +} diff --git a/modules/backend/classes/BackendController.php b/modules/backend/classes/BackendController.php new file mode 100644 index 0000000..f1771af --- /dev/null +++ b/modules/backend/classes/BackendController.php @@ -0,0 +1,347 @@ +middleware(function ($request, $next) { + // Process the request before retrieving controller middleware, to allow for the session and auth data + // to be made available to the controller's constructor. + $response = $next($request); + + // Find requested controller to determine if any middleware has been attached + $pathParts = explode('/', str_replace(Request::root() . '/', '', Request::url())); + if (count($pathParts)) { + // Drop off preceding backend URL part if needed + if (!empty(Config::get('cms.backendUri', 'backend'))) { + array_shift($pathParts); + } + $path = implode('/', $pathParts); + + $requestedController = $this->getRequestedController($path); + if ( + !is_null($requestedController) + && is_array($requestedController) + && count($requestedController['controller']->getMiddleware()) + ) { + $action = $requestedController['action']; + + // Collect applicable middleware and insert middleware into pipeline + $controllerMiddleware = collect($requestedController['controller']->getMiddleware()) + ->reject(function ($data) use ($action) { + return static::methodExcludedByOptions($action, $data['options']); + }) + ->pluck('middleware'); + + foreach ($controllerMiddleware as $middleware) { + $middleware->call($requestedController['controller'], $request, $response); + } + } + } + + return $response; + }); + + $this->extendableConstruct(); + } + + /** + * @inheritDoc + */ + public function callAction($method, $parameters) + { + return parent::callAction($method, array_values($parameters)); + } + + /** + * Pass unhandled URLs to the CMS Controller, if it exists + * + * @param string $url + * @return Response + */ + protected function passToCmsController($url) + { + if ( + in_array('Cms', Config::get('cms.loadModules', [])) && + class_exists('\Cms\Classes\Controller') + ) { + $this->cmsHandling = true; + $response = App::make('Cms\Classes\Controller')->run($url); + if ($response->getStatusCode() !== 404 || !BackendAuth::check()) { + return $response; + } + } + + return Response::make(View::make('backend::404'), 404); + } + + /** + * Finds and serves the requested backend controller. + * If the controller cannot be found, returns the Cms page with the URL /404. + * If the /404 page doesn't exist, returns the system 404 page. + * @param string $url Specifies the requested page URL. + * If the parameter is omitted, the current URL used. + * @return string Returns the processed page content. + */ + public function run($url = null) + { + // Handle NotFoundHttpExceptions in the backend (usually triggered by abort(404)) + Event::listen('exception.beforeRender', function ($exception, $httpCode, $request) { + if ($this->cmsHandling) { + return; + } + + if ($exception instanceof NotFoundHttpException) { + return View::make('backend::404'); + } elseif ( + $exception instanceof HttpException + && $exception->getStatusCode() === 403 + ) { + return View::make('backend::access_denied'); + } + }, 1); + + /* + * Database check + */ + if (!App::hasDatabase()) { + return Config::get('app.debug', false) + ? Response::make(View::make('backend::no_database'), 200) + : $this->passToCmsController($url); + } + + $controllerRequest = $this->getRequestedController($url); + if (!is_null($controllerRequest)) { + return $controllerRequest['controller']->run( + $controllerRequest['action'], + $controllerRequest['params'] + ); + } + + /* + * Fall back on Cms controller + */ + return $this->passToCmsController($url); + } + + /** + * Determines the controller and action to load in the backend via a provided URL. + * + * If a suitable controller is found, this will return an array with the controller class name as a string, the + * action to call as a string and an array of parameters. If a suitable controller and action cannot be found, + * this method will return null. + * + * @param string $url A URL to determine the requested controller and action for + * @return array|null A suitable controller, action and parameters in an array if found, otherwise null. + */ + protected function getRequestedController($url) + { + $params = RouterHelper::segmentizeUrl($url); + + /* + * Look for a Module controller + */ + $module = $params[0] ?? 'backend'; + $controller = $params[1] ?? 'index'; + self::$action = $action = isset($params[2]) ? $this->parseAction($params[2]) : 'index'; + self::$params = $controllerParams = array_slice($params, 3); + $controllerClass = '\\'.$module.'\Controllers\\'.$controller; + if ($controllerObj = $this->findController( + $controllerClass, + $action, + base_path().'/modules' + )) { + return [ + 'controller' => $controllerObj, + 'action' => $action, + 'params' => $controllerParams + ]; + } + + /* + * Look for a Plugin controller + */ + if (count($params) >= 2) { + list($author, $plugin) = $params; + + $pluginCode = ucfirst($author) . '.' . ucfirst($plugin); + if (PluginManager::instance()->isDisabled($pluginCode)) { + return Response::make(View::make('backend::404'), 404); + } + + $controller = $params[2] ?? 'index'; + self::$action = $action = isset($params[3]) ? $this->parseAction($params[3]) : 'index'; + self::$params = $controllerParams = array_slice($params, 4); + $controllerClass = '\\'.$author.'\\'.$plugin.'\Controllers\\'.$controller; + if ($controllerObj = $this->findController( + $controllerClass, + $action, + plugins_path() + )) { + return [ + 'controller' => $controllerObj, + 'action' => $action, + 'params' => $controllerParams + ]; + } + } + + return null; + } + + /** + * This method is used internally. + * Finds a backend controller with a callable action method. + * @param string $controller Specifies a method name to execute. + * @param string $action Specifies a method name to execute. + * @param string $inPath Base path for class file location. + * @return ControllerBase Returns the backend controller object + */ + protected function findController($controller, $action, $inPath) + { + if (isset($this->requestedController)) { + return $this->requestedController; + } + + /* + * Workaround: Composer does not support case insensitivity. + */ + if (!class_exists($controller)) { + $controller = Str::normalizeClassName($controller); + $controllerFile = $inPath.strtolower(str_replace('\\', '/', $controller)) . '.php'; + if ($controllerFile = File::existsInsensitive($controllerFile)) { + include_once $controllerFile; + } + } + + if (!class_exists($controller)) { + return $this->requestedController = null; + } + + $controllerObj = App::make($controller); + + if ($controllerObj->actionExists($action)) { + return $this->requestedController = $controllerObj; + } + + return $this->requestedController = null; + } + + /** + * Process the action name, since dashes are not supported in PHP methods. + * @param string $actionName + * @return string + */ + protected function parseAction($actionName) + { + if (strpos($actionName, '-') !== false) { + return snake_case(camel_case($actionName)); + } + + return $actionName; + } + + /** + * Determine if the given options exclude a particular method. + * + * @param string $method + * @param array $options + * @return bool + */ + protected static function methodExcludedByOptions($method, array $options) + { + return (isset($options['only']) && !in_array($method, (array) $options['only'])) || + (!empty($options['except']) && in_array($method, (array) $options['except'])); + } + + public function __call($name, $params) + { + if ($name === 'extend') { + if (empty($params[0]) || !is_callable($params[0])) { + throw new \InvalidArgumentException('The extend() method requires a callback parameter or closure.'); + } + if ($params[0] instanceof Closure) { + return $params[0]->call($this, $params[1] ?? $this); + } + return Closure::fromCallable($params[0])->call($this, $params[1] ?? $this); + } + + return $this->extendableCall($name, $params); + } + + public static function __callStatic($name, $params) + { + if ($name === 'extend') { + if (empty($params[0])) { + throw new \InvalidArgumentException('The extend() method requires a callback parameter or closure.'); + } + self::extendableExtendCallback($params[0], $params[1] ?? false, $params[2] ?? null); + return; + } + + return self::extendableCallStatic($name, $params); + } +} diff --git a/modules/backend/classes/Controller.php b/modules/backend/classes/Controller.php new file mode 100644 index 0000000..4183901 --- /dev/null +++ b/modules/backend/classes/Controller.php @@ -0,0 +1,823 @@ +action = BackendController::$action; + $this->params = BackendController::$params; + + /* + * Apply $guarded methods to hidden actions + */ + $this->hiddenActions = array_merge($this->hiddenActions, $this->guarded); + + /* + * Define layout and view paths + */ + $this->layout = $this->layout ?: 'default'; + $this->layoutPath = Skin::getActive()->getLayoutPaths(); + $this->viewPath = $this->configPath = $this->guessViewPath(); + + /* + * Add layout paths from the plugin / module context + */ + $relativePath = dirname(dirname(strtolower(str_replace('\\', '/', get_called_class())))); + $this->layoutPath[] = '~/modules/' . $relativePath . '/layouts'; + $this->layoutPath[] = '~/plugins/' . $relativePath . '/layouts'; + + /* + * Create a new instance of the admin user + */ + $this->user = BackendAuth::getUser(); + + /* + * Media Manager widget is available on all back-end pages + */ + if ($this->user && $this->user->hasAccess('media.*')) { + $manager = new MediaManager($this, 'ocmediamanager'); + $manager->bindToController(); + } + + $this->extendableConstruct(); + } + + public function __get($name) + { + return $this->extendableGet($name); + } + + public function __set($name, $value) + { + $this->extendableSet($name, $value); + } + + public function __call($name, $params) + { + if ($name === 'extend') { + if (empty($params[0]) || !is_callable($params[0])) { + throw new \InvalidArgumentException('The extend() method requires a callback parameter or closure.'); + } + if ($params[0] instanceof \Closure) { + return $params[0]->call($this, $params[1] ?? $this); + } + return \Closure::fromCallable($params[0])->call($this, $params[1] ?? $this); + } + + return $this->extendableCall($name, $params); + } + + public static function __callStatic($name, $params) + { + if ($name === 'extend') { + if (empty($params[0])) { + throw new \InvalidArgumentException('The extend() method requires a callback parameter or closure.'); + } + self::extendableExtendCallback($params[0], $params[1] ?? false, $params[2] ?? null); + return; + } + + return self::extendableCallStatic($name, $params); + } + + /** + * Set the navigation context based on the current action & parameters + */ + protected function setNavigationContext(?string $action = null, array $params = []): void + { + $context = BackendMenu::getContext(); + + // @TODO: Support detecting module controllers as well + $currentClass = explode('\\', get_class($this)); + $author = $currentClass[0]; + $plugin = $currentClass[1]; + $controller = $currentClass[count($currentClass) - 1]; + + $owner = $context->owner ?? "$author.$plugin"; + $mainMenuCode = $context->mainMenuCode ?? strtolower($plugin); + $sideMenuCode = $context->sideMenuCode ?? strtolower($controller); + + BackendMenu::setContext($owner, $mainMenuCode, $sideMenuCode); + } + + /** + * Execute the controller action. + * @param string $action The action name. + * @param array $params Routing parameters to pass to the action. + * @return mixed The action result. + */ + public function run($action = null, $params = []) + { + $this->action = $action; + $this->params = $params; + + /* + * Short circuit requests without a valid CSRF token + * @see \System\Traits\SecurityController + */ + if (!in_array(Request::method(), ['HEAD', 'GET', 'OPTIONS']) && !$this->verifyCsrfToken()) { + return Response::make(Lang::get('system::lang.page.invalid_token.label'), 403); + } + + /* + * Check forced HTTPS protocol. + * @see \System\Traits\SecurityController + */ + if (!$this->verifyForceSecure()) { + return Redirect::secure(Request::path()); + } + + /* + * Determine if this request is a public action. + */ + $isPublicAction = in_array($action, $this->publicActions); + + /* + * Check that user is logged in and has permission to view this page + */ + if (!$isPublicAction) { + /* + * Not logged in, redirect to login screen or show ajax error. + */ + if (!BackendAuth::check()) { + return Request::ajax() + ? Response::make(Lang::get('backend::lang.page.access_denied.label'), 403) + : Backend::redirectGuest('backend/auth'); + } + + /* + * Check access groups against the page definition + */ + if ($this->requiredPermissions && !$this->user->hasAnyAccess($this->requiredPermissions)) { + abort(403); + } + } + + /** + * @event backend.page.beforeDisplay + * Provides an opportunity to override backend page content + * + * Example usage: + * + * Event::listen('backend.page.beforeDisplay', function ((\Backend\Classes\Controller) $backendController, (string) $action, (array) $params) { + * trace_log('redirect all backend pages to google'); + * return \Redirect::to('https://google.com'); + * }); + * + * Or + * + * $backendController->bindEvent('page.beforeDisplay', function ((string) $action, (array) $params) { + * trace_log('redirect all backend pages to google'); + * return \Redirect::to('https://google.com'); + * }); + * + */ + if ($event = $this->fireSystemEvent('backend.page.beforeDisplay', [$action, $params])) { + return $event; + } + + /* + * Set the admin preference locale + */ + BackendPreference::setAppLocale(); + BackendPreference::setAppFallbackLocale(); + + /* + * Set the navigation context + */ + $this->setNavigationContext($action, $params); + + /* + * Execute AJAX event + */ + if ($ajaxResponse = $this->execAjaxHandlers()) { + $result = $ajaxResponse; + } + + /* + * Execute postback handler + */ + elseif ( + ($handler = post('_handler')) && + $this->verifyCsrfToken() + ) { + $this->validateHandlerName($handler); + + if ( + ($handlerResponse = $this->runAjaxHandler($handler)) && + $handlerResponse !== true + ) { + $result = $handlerResponse; + } + } + + /* + * Execute page action + */ + else { + $result = $this->execPageAction($action, $params); + } + + /* + * Prepare and return response + * @see \System\Traits\ResponseMaker + */ + return $this->makeResponse($result); + } + + /** + * This method is used internally. + * Determines whether an action with the specified name exists. + * Action must be a class public method. Action name can not be prefixed with the underscore character. + * @param string $name Specifies the action name. + * @param bool $internal Allow protected actions. + * @return boolean + */ + public function actionExists($name, $internal = false) + { + if (!strlen($name) || substr($name, 0, 1) == '_' || !$this->methodExists($name)) { + return false; + } + + foreach ($this->hiddenActions as $method) { + if (strtolower($name) == strtolower($method)) { + return false; + } + } + + $ownMethod = method_exists($this, $name); + + if ($ownMethod) { + $methodInfo = new \ReflectionMethod($this, $name); + + /* + * Only allow lowercase actions. Compare the resolved method name rather than the + * requested one - PHP method names are case-insensitive, so a lowercased URL + * segment would otherwise pass this check and still resolve to the mixed-case + * method (eg. "index_onemptylog" reaching index_onEmptyLog()). + */ + if (strtolower($methodInfo->getName()) !== $methodInfo->getName()) { + return false; + } + + $public = $methodInfo->isPublic(); + if ($public) { + return true; + } + } + /* + * Extension methods are resolved through a case-sensitive lookup, so the requested + * name is already the canonical one. + */ + elseif (strtolower($name) !== $name) { + return false; + } + + if ($internal && (($ownMethod && $methodInfo->isProtected()) || !$ownMethod)) { + return true; + } + + if (!$ownMethod) { + return true; + } + + return false; + } + + /** + * Returns a URL for this controller and supplied action. + */ + public function actionUrl($action = null, $path = null) + { + if ($action === null) { + $action = $this->action; + } + + $class = get_called_class(); + $uriPath = dirname(dirname(strtolower(str_replace('\\', '/', $class)))); + $controllerName = strtolower(class_basename($class)); + + $url = $uriPath.'/'.$controllerName.'/'.$action; + if ($path) { + $url .= '/'.$path; + } + + return Backend::url($url); + } + + /** + * Invokes the current controller action without rendering a view, + * used by AJAX handler that may rely on the logic inside the action. + */ + public function pageAction() + { + if (!$this->action) { + return; + } + + $this->suppressView = true; + $this->execPageAction($this->action, $this->params); + } + + /** + * This method is used internally. + * Invokes the controller action and loads the corresponding view. + * @param string $actionName Specifies a action name to execute. + * @param array $parameters A list of the action parameters. + */ + protected function execPageAction($actionName, $parameters) + { + $result = null; + + if (!$this->actionExists($actionName)) { + if (Config::get('app.debug', false)) { + throw new SystemException(sprintf( + "Action %s is not found in the controller %s", + $actionName, + get_class($this) + )); + } else { + Response::make(View::make('backend::404'), 404); + } + } + + // Execute the action + $result = call_user_func_array([$this, $actionName], $parameters); + + // Expecting \Response and \RedirectResponse + if ($result instanceof \Symfony\Component\HttpFoundation\Response) { + return $result; + } + + // No page title + if (!$this->pageTitle) { + $this->pageTitle = 'backend::lang.page.untitled'; + } + + // Load the view + if (!$this->suppressView && $result === null) { + return $this->makeView($actionName); + } + + return $this->makeViewContent((string) $result); + } + + /** + * Returns the AJAX handler for the current request, if available. + * @return string + */ + public function getAjaxHandler() + { + if (!Request::ajax() || Request::method() != 'POST') { + return null; + } + + if ($handler = Request::header('X_WINTER_REQUEST_HANDLER')) { + return trim($handler); + } + + return null; + } + + /** + * Validates the AJAX handler name follows the expected format. + * + * @throws \Winter\Storm\Exception\SystemException if the handler name is invalid + */ + protected function validateHandlerName(string $handler): void + { + if (!preg_match('/^(?:\w+\:{2})?on[A-Z]{1}[\w+]*$/', $handler)) { + throw new SystemException(Lang::get('backend::lang.ajax_handler.invalid_name', ['name' => $handler])); + } + } + + /** + * This method is used internally. + * Invokes a controller event handler and loads the supplied partials. + */ + protected function execAjaxHandlers() + { + if ($handler = $this->getAjaxHandler()) { + try { + /* + * Validate the handler name + */ + $this->validateHandlerName($handler); + + /* + * Validate the handler partial list + */ + if ($partialList = trim(Request::header('X_WINTER_REQUEST_PARTIALS'))) { + $partialList = explode('&', $partialList); + + foreach ($partialList as $partial) { + if (!preg_match('/^(?!.*\/\/)[a-z0-9\_][a-z0-9\_\-\/]*$/i', $partial)) { + throw new SystemException(Lang::get('backend::lang.partial.invalid_name', ['name'=>$partial])); + } + } + } + else { + $partialList = []; + } + + $responseContents = []; + + /* + * Execute the handler + */ + if (!$result = $this->runAjaxHandler($handler)) { + throw new SystemException(Lang::get('backend::lang.ajax_handler.not_found', ['name'=>$handler])); + } + + /* + * Render partials and return the response as array that will be converted to JSON automatically. + */ + foreach ($partialList as $partial) { + $responseContents[$partial] = $this->makePartial($partial); + } + + /* + * If the handler returned a redirect, process the URL and dispose of it so + * framework.js knows to redirect the browser and not the request! + */ + if ($result instanceof RedirectResponse) { + $responseContents['X_WINTER_REDIRECT'] = $result->getTargetUrl(); + $result = null; + } + /* + * No redirect is used, look for any flash messages + */ + elseif (Flash::check()) { + $responseContents['#layout-flash-messages'] = $this->makeLayoutPartial('flash_messages'); + } + + /* + * Detect assets + */ + if ($this->hasAssetsDefined()) { + $responseContents['X_WINTER_ASSETS'] = $this->getAssetPaths(); + } + + /* + * If the handler returned an array, we should add it to output for rendering. + * If it is a string, add it to the array with the key "result". + * If an object, pass it to Laravel as a response object. + */ + if (is_array($result)) { + $responseContents = array_merge($responseContents, $result); + } + elseif (is_string($result)) { + $responseContents['result'] = $result; + } + elseif (is_object($result)) { + return $result; + } + + return Response::make()->setContent($responseContents); + } + catch (ValidationException $ex) { + /* + * Handle validation error gracefully + */ + Flash::error($ex->getMessage()); + $responseContents = []; + $responseContents['#layout-flash-messages'] = $this->makeLayoutPartial('flash_messages'); + $responseContents['X_WINTER_ERROR_FIELDS'] = $ex->getFields(); + throw new AjaxException($responseContents); + } + catch (MassAssignmentException $ex) { + throw new ApplicationException(Lang::get('backend::lang.model.mass_assignment_failed', ['attribute' => $ex->getMessage()])); + } + catch (Exception $ex) { + throw $ex; + } + } + + return null; + } + + /** + * Tries to find and run an AJAX handler in the page action. + * The method stops as soon as the handler is found. + * @return boolean Returns true if the handler was found. Returns false otherwise. + */ + protected function runAjaxHandler($handler) + { + /** + * @event backend.ajax.beforeRunHandler + * Provides an opportunity to modify an AJAX request + * + * The parameter provided is `$handler` (the requested AJAX handler to be run) + * + * Example usage (forwards AJAX handlers to a backend widget): + * + * Event::listen('backend.ajax.beforeRunHandler', function ((\Backend\Classes\Controller) $controller, (string) $handler) { + * if (strpos($handler, '::')) { + * list($componentAlias, $handlerName) = explode('::', $handler); + * if ($componentAlias === $this->getBackendWidgetAlias()) { + * return $this->backendControllerProxy->runAjaxHandler($handler); + * } + * } + * }); + * + * Or + * + * $this->controller->bindEvent('ajax.beforeRunHandler', function ((string) $handler) { + * if (strpos($handler, '::')) { + * list($componentAlias, $handlerName) = explode('::', $handler); + * if ($componentAlias === $this->getBackendWidgetAlias()) { + * return $this->backendControllerProxy->runAjaxHandler($handler); + * } + * } + * }); + * + */ + if ($event = $this->fireSystemEvent('backend.ajax.beforeRunHandler', [$handler])) { + return $event; + } + + /* + * Process Widget handler + */ + if (strpos($handler, '::')) { + list($widgetName, $handlerName) = explode('::', $handler); + + /* + * Execute the page action so widgets are initialized + */ + $this->pageAction(); + + if ($this->fatalError) { + throw new SystemException($this->fatalError); + } + + if (!isset($this->widget->{$widgetName})) { + throw new SystemException(Lang::get('backend::lang.widget.not_bound', ['name'=>$widgetName])); + } + + if (($widget = $this->widget->{$widgetName}) && $widget->methodExists($handlerName)) { + $result = $this->runAjaxHandlerForWidget($widget, $handlerName); + return $result ?: true; + } + } + else { + /* + * Process page specific handler (index_onSomething) + */ + $pageHandler = $this->action . '_' . $handler; + + if ($this->methodExists($pageHandler)) { + $result = call_user_func_array([$this, $pageHandler], array_values($this->params)); + return $result ?: true; + } + + /* + * Process page global handler (onSomething) + */ + if ($this->methodExists($handler)) { + $result = call_user_func_array([$this, $handler], array_values($this->params)); + return $result ?: true; + } + + /* + * Cycle each widget to locate a usable handler (widget::onSomething) + */ + $this->suppressView = true; + $this->execPageAction($this->action, $this->params); + + foreach ((array) $this->widget as $widget) { + if ($widget->methodExists($handler)) { + $result = $this->runAjaxHandlerForWidget($widget, $handler); + return $result ?: true; + } + } + } + + /* + * Generic handler that does nothing + */ + if ($handler == 'onAjax') { + return true; + } + + return false; + } + + /** + * Specific code for executing an AJAX handler for a widget. + * This will append the widget view paths to the controller and merge the vars. + * @return mixed + */ + protected function runAjaxHandlerForWidget($widget, $handler) + { + $this->prependViewPath($widget->getViewPaths()); + + $result = call_user_func_array([$widget, $handler], array_values($this->params)); + + $this->vars = $widget->vars + $this->vars; + + return $result; + } + + /** + * Returns the controllers public actions. + */ + public function getPublicActions() + { + return $this->publicActions; + } + + /** + * Returns a unique ID for the controller and route. Useful in creating HTML markup. + */ + public function getId($suffix = null) + { + $id = class_basename(get_called_class()) . '-' . $this->action; + if ($suffix !== null) { + $id .= '-' . $suffix; + } + + return $id; + } + + // + // Hints + // + + /** + * Renders a hint partial, used for displaying informative information that + * can be hidden by the user. If you don't want to render a partial, you can + * supply content via the 'content' key of $params. + * @param string $name Unique key name + * @param string $partial Reference to content (partial name) + * @param array $params Extra parameters + * @return string + */ + public function makeHintPartial($name, $partial = null, $params = []) + { + if (is_array($partial)) { + $params = $partial; + $partial = null; + } + + if (!$partial) { + $partial = array_get($params, 'partial', $name); + } + + return $this->makeLayoutPartial('hint', [ + 'hintName' => $name, + 'hintPartial' => $partial, + 'hintContent' => array_get($params, 'content'), + 'hintParams' => $params + ] + $params); + } + + /** + * Ajax handler to hide a backend hint, once hidden the partial + * will no longer display for the user. + * @return void + */ + public function onHideBackendHint() + { + if (!$name = post('name')) { + throw new ApplicationException('Missing a hint name.'); + } + + $preferences = UserPreference::forUser(); + $hiddenHints = $preferences->get('backend::hints.hidden', []); + $hiddenHints[$name] = 1; + + $preferences->set('backend::hints.hidden', $hiddenHints); + } + + /** + * Checks if a hint has been hidden by the user. + * @param string $name Unique key name + * @return boolean + */ + public function isBackendHintHidden($name) + { + $hiddenHints = UserPreference::forUser()->get('backend::hints.hidden', []); + return array_key_exists($name, $hiddenHints); + } +} diff --git a/modules/backend/classes/ControllerBehavior.php b/modules/backend/classes/ControllerBehavior.php new file mode 100644 index 0000000..9effeb7 --- /dev/null +++ b/modules/backend/classes/ControllerBehavior.php @@ -0,0 +1,168 @@ +controller = $controller; + $this->viewPath = $this->configPath = $this->guessViewPath('/partials'); + $this->assetPath = $this->guessViewPath('/assets', true); + + /* + * Validate controller properties + */ + foreach ($this->requiredProperties as $property) { + if (!isset($controller->{$property})) { + throw new ApplicationException(Lang::get('system::lang.behavior.missing_property', [ + 'class' => get_class($controller), + 'property' => $property, + 'behavior' => get_called_class() + ])); + } + } + + // Hide all methods that aren't explicitly listed as actions + if (is_array($this->actions)) { + $this->hideAction(array_diff(get_class_methods(get_class($this)), $this->actions)); + } + + // Include this behavior's default views in the controller's view paths + $this->controller->appendViewPath($this->guessViewPath('/views')); + } + + /** + * Sets the configuration values + * @param mixed $config Config object or array + * @param array $required Required config items + */ + public function setConfig($config, $required = []) + { + $this->config = $this->makeConfig($config, $required); + } + + /** + * Safe accessor for configuration values. + * @param string $name Config name, supports array names like "field[key]" + * @param mixed $default Default value if nothing is found + * @return string + */ + public function getConfig($name = null, $default = null) + { + /* + * Return all config + */ + if ($name === null) { + return $this->config; + } + + /* + * Array field name, eg: field[key][key2][key3] + */ + $keyParts = HtmlHelper::nameToArray($name); + + /* + * First part will be the field name, pop it off + */ + $fieldName = array_shift($keyParts); + if (!isset($this->config->{$fieldName})) { + return $default; + } + + $result = $this->config->{$fieldName}; + + /* + * Loop the remaining key parts and build a result + */ + foreach ($keyParts as $key) { + if (!is_array($result) || !array_key_exists($key, $result)) { + return $default; + } + + $result = $result[$key]; + } + + return $result; + } + + /** + * Protects a public method from being available as an controller action. + * These methods could be defined in a controller to override a behavior default action. + * Such methods should be defined as public, to allow the behavior object to access it. + * By default public methods of a controller are considered as actions. + * To prevent this occurrence, methods should be hidden by using this method. + * @param mixed $methodName Specifies a method name. + */ + protected function hideAction($methodName) + { + if (!is_array($methodName)) { + $methodName = [$methodName]; + } + + $this->controller->hiddenActions = array_merge($this->controller->hiddenActions, $methodName); + } + + /** + * Makes all views in context of the controller, not the behavior. + * @param string $filePath Absolute path to the view file. + * @param array $extraParams Parameters that should be available to the view. + * @return string + */ + public function makeFileContents($filePath, $extraParams = []) + { + $this->controller->vars = array_merge($this->controller->vars, $this->vars); + return $this->controller->makeFileContents($filePath, $extraParams); + } + + /** + * Returns true in case if a specified method exists in the extended controller. + * @param string $methodName Specifies the method name + * @return bool + */ + protected function controllerMethodExists($methodName) + { + return method_exists($this->controller, $methodName); + } +} diff --git a/modules/backend/classes/FilterScope.php b/modules/backend/classes/FilterScope.php new file mode 100644 index 0000000..1fa39c4 --- /dev/null +++ b/modules/backend/classes/FilterScope.php @@ -0,0 +1,168 @@ +scopeName = $scopeName; + $this->label = $label; + } + + /** + * Specifies a scope control rendering mode. Supported modes are: + * - group - filter by a group of IDs. Default. + * - checkbox - filter by a simple toggle switch. + * @param string $type Specifies a render mode as described above + * @param array $config A list of render mode specific config. + */ + public function displayAs($type, $config = []) + { + $this->type = strtolower($type) ?: $this->type; + $this->config = $this->evalConfig($config); + return $this; + } + + /** + * Process options and apply them to this object. + * @param array $config + * @return array + */ + protected function evalConfig($config) + { + if ($config === null) { + $config = []; + } + + /* + * Standard config:property values + */ + $applyConfigValues = [ + 'options', + 'dependsOn', + 'context', + 'default', + 'conditions', + 'scope', + 'cssClass', + 'nameFrom', + 'descriptionFrom', + 'disabled', + ]; + + foreach ($applyConfigValues as $value) { + if (array_key_exists($value, $config)) { + $this->{$value} = $config[$value]; + } + } + + return $config; + } + + /** + * Returns a value suitable for the scope id property. + */ + public function getId($suffix = null) + { + $id = 'scope'; + $id .= '-'.$this->scopeName; + + if ($suffix) { + $id .= '-'.$suffix; + } + + if ($this->idPrefix) { + $id = $this->idPrefix . '-' . $id; + } + + return HtmlHelper::nameToId($id); + } +} diff --git a/modules/backend/classes/FormField.php b/modules/backend/classes/FormField.php new file mode 100644 index 0000000..53c2a46 --- /dev/null +++ b/modules/backend/classes/FormField.php @@ -0,0 +1,764 @@ + + */ + public $arrayName; + + /** + * @var string A prefix to the field identifier so it can be totally unique. + */ + public $idPrefix; + + /** + * @var string Form field label. + */ + public $label; + + /** + * @var string Form field value. + */ + public $value; + + /** + * @var string Model attribute to use for the display value. + */ + public $valueFrom; + + /** + * @var string Specifies a default value for supported fields. + */ + public $defaults; + + /** + * @var string Model attribute to use for the default value. + */ + public $defaultFrom; + + /** + * @var string Specifies if this field belongs to a tab. + */ + public $tab; + + /** + * @var string Display mode. Text, textarea + */ + public $type = 'text'; + + /** + * @var string Field options. + */ + public $options; + + /** + * @var string Specifies a side. Possible values: auto, left, right, full. + */ + public $span = 'full'; + + /** + * @var string|int Specifies a size. Possible values for textarea: tiny, small, large, huge, giant. + */ + public $size; + + /** + * @var string Specifies contextual visibility of this form field. + */ + public $context; + + /** + * @var bool Specifies if this field is mandatory. + */ + public $required; + + /** + * @var bool Specify if the field is read-only or not. + */ + public $readOnly = false; + + /** + * @var bool Specify if the field is disabled or not. + */ + public $disabled = false; + + /** + * @var bool Specify if the field is hidden. Hiddens fields are not included in postbacks. + */ + public $hidden = false; + + /** + * @var bool Specifies if this field stretch to fit the page height. + */ + public $stretch = false; + + /** + * @var string Specifies a comment to accompany the field + */ + public $comment = ''; + + /** + * @var string Specifies the comment position. + */ + public $commentPosition = 'below'; + + /** + * @var string Specifies if the comment is in HTML format. + */ + public $commentHtml = false; + + /** + * @var string Specifies a message to display when there is no value supplied (placeholder). + */ + public $placeholder = ''; + + /** + * @var array Contains a list of attributes specified in the field configuration. + */ + public $attributes; + + /** + * @var string Specifies a CSS class to attach to the field container. + */ + public $cssClass; + + /** + * @var string Specifies a path for partial-type fields. + */ + public $path; + + /** + * @var array Raw field configuration. + */ + public $config; + + /** + * @var array Other field names this field depends on, when the other fields are modified, this field will update. + */ + public $dependsOn; + + /** + * @var array Other field names this field can be triggered by, see the Trigger API documentation. + */ + public $trigger; + + /** + * @var array Other field names text is converted in to a URL, slug or file name value in this field. + */ + public $preset; + + /** + * Constructor. + * @param string $fieldName The name of the field + * @param string $label The label of the field + */ + public function __construct($fieldName, $label) + { + $this->fieldName = $fieldName; + $this->label = $label; + } + + /** + * If this field belongs to a tab. + */ + public function tab($value) + { + $this->tab = $value; + return $this; + } + + /** + * Sets a side of the field on a form. + * @param string $value Specifies a side. Possible values: left, right, full + */ + public function span($value = 'full') + { + $this->span = $value; + return $this; + } + + /** + * Sets the size of the field on a form. + * @param string $value Specifies a size. Possible values: tiny, small, large, huge, giant + */ + public function size($value = 'large') + { + $this->size = $value; + return $this; + } + + /** + * Sets field options, for dropdowns, radio lists and checkbox lists. + * @param array $value + * @return self + */ + public function options($value = null) + { + if ($value === null) { + if (is_array($this->options)) { + return $this->options; + } elseif (is_callable($this->options)) { + $callable = $this->options; + return $callable(); + } elseif (is_string($this->options) && is_array($options = Lang::get($this->options))) { + return $options; + } + + return []; + } + + $this->options = $value; + + return $this; + } + + /** + * Specifies a field control rendering mode. Supported modes are: + * - text - creates a text field. Default for varchar column types. + * - textarea - creates a textarea control. Default for text column types. + * - dropdown - creates a drop-down list. Default for reference-based columns. + * - radio - creates a set of radio buttons. + * - checkbox - creates a single checkbox. + * - checkboxlist - creates a checkbox list. + * - switch - creates a switch field. + * @param string $type Specifies a render mode as described above + * @param array $config A list of render mode specific config. + */ + public function displayAs($type, $config = []) + { + if (in_array($type, ['textarea', 'widget'])) { + // defaults to 'large' + $this->size = 'large'; + } + + $this->type = strtolower($type) ?: $this->type; + $this->config = $this->evalConfig($config); + + return $this; + } + + /** + * Process options and apply them to this object. + * @param array $config + * @return array + */ + protected function evalConfig($config) + { + if ($config === null) { + $config = []; + } + + /* + * Standard config:property values + */ + $applyConfigValues = [ + 'commentHtml', + 'context', + 'cssClass', + 'dependsOn', + 'disabled', + 'hidden', + 'path', + 'placeholder', + 'preset', + 'readOnly', + 'required', + 'stretch', + 'trigger', + ]; + + foreach ($applyConfigValues as $value) { + if (array_key_exists($value, $config)) { + $this->{$value} = $config[$value]; + } + } + + /* + * Custom applicators + */ + if (isset($config['options'])) { + $this->options($config['options']); + } + if (isset($config['span'])) { + $this->span($config['span']); + } + if (isset($config['size'])) { + $this->size($config['size']); + } + if (isset($config['tab'])) { + $this->tab($config['tab']); + } + if (isset($config['commentAbove'])) { + $this->comment($config['commentAbove'], 'above'); + } + if (isset($config['comment'])) { + $this->comment($config['comment']); + } + if (isset($config['default'])) { + $this->defaults = $config['default']; + } + if (isset($config['defaultFrom'])) { + $this->defaultFrom = $config['defaultFrom']; + } + if (isset($config['attributes'])) { + $this->attributes($config['attributes']); + } + if (isset($config['containerAttributes'])) { + $this->attributes($config['containerAttributes'], 'container'); + } + + if (isset($config['valueFrom'])) { + $this->valueFrom = $config['valueFrom']; + } + else { + $this->valueFrom = $this->fieldName; + } + + return $config; + } + + /** + * Adds a text comment above or below the field. + * @param string $text Specifies a comment text. + * @param string $position Specifies a comment position. + * @param bool $isHtml Set to true if you use HTML formatting in the comment + * Supported values are 'below' and 'above' + */ + public function comment($text, $position = 'below', $isHtml = null) + { + $this->comment = $text; + $this->commentPosition = $position; + + if ($isHtml !== null) { + $this->commentHtml = $isHtml; + } + + return $this; + } + + /** + * Determine if the provided value matches this field's value. + * @param string $value + * @return bool + */ + public function isSelected($value = true) + { + if ($this->value === null) { + return false; + } + + $value = ($value instanceof BackedEnum) ? $value->value : $value; + $currentValue = ($this->value instanceof BackedEnum) ? $this->value->value : $this->value; + + return (string) $value === (string) $currentValue; + } + + /** + * Sets the attributes for this field in a given position. + * - field: Attributes are added to the form field element (input, select, textarea, etc) + * - container: Attributes are added to the form field container (div.form-group) + * @param array $items + * @param string $position + * @return void + */ + public function attributes($items, $position = 'field') + { + if (!is_array($items)) { + return; + } + + $multiArray = array_filter($items, 'is_array'); + if (!$multiArray) { + $this->attributes[$position] = $items; + return; + } + + foreach ($items as $_position => $_items) { + $this->attributes($_items, $_position); + } + + return $this; + } + + /** + * Checks if the field has the supplied [unfiltered] attribute. + * @param string $name + * @param string $position + * @return bool + */ + public function hasAttribute($name, $position = 'field') + { + if (!isset($this->attributes[$position])) { + return false; + } + + return array_key_exists($name, $this->attributes[$position]); + } + + /** + * Returns the attributes for this field at a given position. + * @param string $position + * @return array + */ + public function getAttributes($position = 'field', $htmlBuild = true) + { + $result = array_get($this->attributes, $position, []); + $result = $this->filterAttributes($result, $position); + + // Field is required, so add the "required" attribute + if ($position === 'field' && $this->required && (!isset($result['required']) || $result['required'])) { + $result['required'] = ''; + } elseif ($position === 'field' && isset($result['required']) && !$result['required']) { + // The "required" attribute is set and falsy, so unset it + unset($result['required']); + } + + return $htmlBuild ? Html::attributes($result) : $result; + } + + /** + * Adds any circumstantial attributes to the field based on other + * settings, such as the 'disabled' option. + * @param array $attributes + * @param string $position + * @return array + */ + protected function filterAttributes($attributes, $position = 'field') + { + $position = strtolower($position); + + $attributes = $this->filterTriggerAttributes($attributes, $position); + $attributes = $this->filterPresetAttributes($attributes, $position); + + if ($position == 'field' && $this->disabled) { + $attributes = $attributes + ['disabled' => 'disabled']; + } + + if ($position == 'field' && $this->readOnly) { + $attributes = $attributes + ['readonly' => 'readonly']; + + if ($this->type == 'checkbox' || $this->type == 'switch') { + $attributes = $attributes + ['onclick' => 'return false;']; + } + } + + return $attributes; + } + + /** + * Adds attributes used specifically by the Trigger API + * @param array $attributes + * @param string $position + * @return array + */ + protected function filterTriggerAttributes($attributes, $position = 'field') + { + if (!$this->trigger || !is_array($this->trigger)) { + return $attributes; + } + + $triggerAction = array_get($this->trigger, 'action'); + $triggerField = array_get($this->trigger, 'field'); + $triggerCondition = array_get($this->trigger, 'condition'); + $triggerForm = $this->arrayName; + $triggerMulti = ''; + + // Apply these to container + if (in_array($triggerAction, ['hide', 'show']) && $position != 'container') { + return $attributes; + } + + // Apply these to field/input + if (in_array($triggerAction, ['enable', 'disable', 'empty']) && $position != 'field') { + return $attributes; + } + + // Reduce the field reference for the trigger condition field + $triggerFieldParentLevel = Str::getPrecedingSymbols($triggerField, self::HIERARCHY_UP); + if ($triggerFieldParentLevel > 0) { + // Remove the preceding symbols from the trigger field name + $triggerField = substr($triggerField, $triggerFieldParentLevel); + $triggerForm = HtmlHelper::reduceNameHierarchy($triggerForm, $triggerFieldParentLevel); + } + + // Preserve multi field types + if (Str::endsWith($triggerField, '[]')) { + $triggerField = substr($triggerField, 0, -2); + $triggerMulti = '[]'; + } + + // Final compilation + if ($this->arrayName) { + $fullTriggerField = $triggerForm.'['.implode('][', HtmlHelper::nameToArray($triggerField)).']'.$triggerMulti; + } + else { + $fullTriggerField = $triggerField.$triggerMulti; + } + + $newAttributes = [ + 'data-trigger' => '[name="'.$fullTriggerField.'"]', + 'data-trigger-action' => $triggerAction, + 'data-trigger-condition' => $triggerCondition, + 'data-trigger-closest-parent' => 'form, div[data-control="formwidget"]' + ]; + + return $attributes + $newAttributes; + } + + /** + * Adds attributes used specifically by the Input Preset API + * @param array $attributes + * @param string $position + * @return array + */ + protected function filterPresetAttributes($attributes, $position = 'field') + { + if (!$this->preset || $position != 'field') { + return $attributes; + } + + if (!is_array($this->preset)) { + $this->preset = ['field' => $this->preset, 'type' => 'slug']; + } + + $presetField = array_get($this->preset, 'field'); + $presetType = array_get($this->preset, 'type'); + + if ($this->arrayName) { + $fullPresetField = $this->arrayName.'['.implode('][', HtmlHelper::nameToArray($presetField)).']'; + } + else { + $fullPresetField = $presetField; + } + + $newAttributes = [ + 'data-input-preset' => '[name="'.$fullPresetField.'"]', + 'data-input-preset-type' => $presetType, + 'data-input-preset-closest-parent' => 'form' + ]; + + if ($prefixInput = array_get($this->preset, 'prefixInput')) { + $newAttributes['data-input-preset-prefix-input'] = $prefixInput; + } + + return $attributes + $newAttributes; + } + + /** + * Returns a value suitable for the field name property. + * @param string $arrayName Specify a custom array name + * @return string + */ + public function getName($arrayName = null) + { + if ($arrayName === null) { + $arrayName = $this->arrayName; + } + + if ($arrayName) { + return $arrayName.'['.implode('][', HtmlHelper::nameToArray($this->fieldName)).']'; + } + + return $this->fieldName; + } + + /** + * Returns a value suitable for the field id property. + * @param string $suffix Specify a suffix string + * @return string + */ + public function getId($suffix = null) + { + $id = 'field'; + if ($this->arrayName) { + $id .= '-'.$this->arrayName; + } + + $id .= '-'.$this->fieldName; + + if ($suffix) { + $id .= '-'.$suffix; + } + + if ($this->idPrefix) { + $id = $this->idPrefix . '-' . $id; + } + + return HtmlHelper::nameToId($id); + } + + /** + * Returns a raw config item value. + * @param string $value + * @param string $default + * @return mixed + */ + public function getConfig($value, $default = null) + { + return array_get($this->config, $value, $default); + } + + /** + * Returns this fields value from a supplied data set, which can be + * an array or a model or another generic collection. + * @param mixed $data + * @param mixed $default + * @return mixed + */ + public function getValueFromData($data, $default = null) + { + $fieldName = $this->valueFrom ?: $this->fieldName; + return $this->getFieldNameFromData($fieldName, $data, $default); + } + + /** + * Returns the default value for this field, the supplied data is used + * to source data when defaultFrom is specified. + * @param mixed $data + * @return mixed + */ + public function getDefaultFromData($data) + { + if ($this->defaultFrom) { + return $this->getFieldNameFromData($this->defaultFrom, $data); + } + + if ($this->defaults !== '') { + return $this->defaults; + } + + return null; + } + + /** + * Returns the final model and attribute name of a nested attribute. Eg: + * + * list($model, $attribute) = $this->resolveAttribute('person[phone]'); + * + * @param string $attribute. + * @return array + */ + public function resolveModelAttribute($model, $attribute = null) + { + if ($attribute === null) { + $attribute = $this->valueFrom ?: $this->fieldName; + } + + $parts = is_array($attribute) ? $attribute : HtmlHelper::nameToArray($attribute); + $last = array_pop($parts); + + foreach ($parts as $part) { + $model = $model->{$part}; + } + + return [$model, $last]; + } + + /** + * Internal method to extract the value of a field name from a data set. + * @param string $fieldName + * @param mixed $data + * @param mixed $default + * @return mixed + */ + protected function getFieldNameFromData($fieldName, $data, $default = null) + { + /* + * Array field name, eg: field[key][key2][key3] + */ + $keyParts = HtmlHelper::nameToArray($fieldName); + $lastField = end($keyParts); + $result = $data; + + /* + * Loop the field key parts and build a value. + * To support relations only the last field should return the + * relation value, all others will look up the relation object as normal. + */ + foreach ($keyParts as $key) { + if ($result instanceof Model && $result->hasRelation($key)) { + if ($key == $lastField) { + $result = $result->getRelationValue($key) ?: $default; + } else { + $result = $result->{$key}; + } + } elseif (is_array($result)) { + if (!array_key_exists($key, $result)) { + return $default; + } + $result = $result[$key]; + } else { + if (!isset($result->{$key})) { + return $default; + } + $result = $result->{$key}; + } + } + + if ($result instanceof BackedEnum) { + $result = $result->value; + } + + return $result; + } + + /** + * Implements the getter functionality. + * @param string $name + */ + public function __get($name) + { + if (is_array($this->config) && array_key_exists($name, $this->config)) { + return array_get($this->config, $name); + } + if (property_exists($this, $name)) { + return $this->{$name}; + } + return null; + } + + /** + * Determine if an attribute exists on the object. + * @param string $name + */ + public function __isset($name) + { + if (is_array($this->config) && array_key_exists($name, $this->config)) { + return true; + } + return property_exists($this, $name) && !is_null($this->{$name}); + } +} diff --git a/modules/backend/classes/FormTabs.php b/modules/backend/classes/FormTabs.php new file mode 100644 index 0000000..381b82b --- /dev/null +++ b/modules/backend/classes/FormTabs.php @@ -0,0 +1,279 @@ +section = strtolower($section) ?: $this->section; + $this->evalConfig($config); + + if ($this->section == self::SECTION_OUTSIDE) { + $this->suppressTabs = true; + } + } + + /** + * Process options and apply them to this object. + */ + protected function evalConfig(array $config): void + { + if (array_key_exists('defaultTab', $config)) { + $this->defaultTab = $config['defaultTab']; + } + + if (array_key_exists('icons', $config)) { + $this->icons = $config['icons']; + } + + if (array_key_exists('stretch', $config)) { + $this->stretch = $config['stretch']; + } + + if (array_key_exists('suppressTabs', $config)) { + $this->suppressTabs = $config['suppressTabs']; + } + + if (array_key_exists('cssClass', $config)) { + $this->cssClass = $config['cssClass']; + } + + if (array_key_exists('paneCssClass', $config)) { + $this->paneCssClass = $config['paneCssClass']; + } + + if (array_key_exists('linkable', $config)) { + $this->linkable = (bool) $config['linkable']; + } + + if (array_key_exists('lazy', $config)) { + $this->lazy = $config['lazy']; + } + } + + /** + * Add a field to the collection of tabs. + * @param string $name + * @param FormField $field + * @param string $tab + */ + public function addField($name, FormField $field, $tab = null) + { + if (!$tab) { + $tab = $this->defaultTab; + } + + $this->fields[$tab][$name] = $field; + } + + /** + * Remove a field from all tabs by name. + * @param string $name + * @return boolean + */ + public function removeField($name) + { + foreach ($this->fields as $tab => $fields) { + foreach ($fields as $fieldName => $field) { + if ($fieldName == $name) { + unset($this->fields[$tab][$fieldName]); + + /* + * Remove empty tabs from collection + */ + if (!count($this->fields[$tab])) { + unset($this->fields[$tab]); + } + + return true; + } + } + } + + return false; + } + + /** + * Returns true if any fields have been registered for these tabs + * @return boolean + */ + public function hasFields() + { + return count($this->fields) > 0; + } + + /** + * Returns an array of the registered fields, including tabs. + * @return array + */ + public function getFields() + { + return $this->fields; + } + + /** + * Returns an array of the registered fields, without tabs. + * @return array + */ + public function getAllFields() + { + $tablessFields = []; + + foreach ($this->getFields() as $tab) { + $tablessFields += $tab; + } + + return $tablessFields; + } + + /** + * Returns an icon for the tab based on the tab's name. + * @param string $name + * @return string + */ + public function getIcon($name) + { + if (!empty($this->icons[$name])) { + return $this->icons[$name]; + } + } + + /** + * Returns a tab pane CSS class. + * @param string $index + * @param string $label + * @return string + */ + public function getPaneCssClass($index = null, $label = null) + { + if (is_string($this->paneCssClass)) { + return $this->paneCssClass; + } + + if ($index !== null && isset($this->paneCssClass[$index])) { + return $this->paneCssClass[$index]; + } + + if ($label !== null && isset($this->paneCssClass[$label])) { + return $this->paneCssClass[$label]; + } + } + + /** + * Get an iterator for the items. + */ + public function getIterator(): Traversable + { + return new ArrayIterator( + $this->suppressTabs + ? $this->getAllFields() + : $this->getFields() + ); + } + + /** + * ArrayAccess implementation + */ + public function offsetSet($offset, $value): void + { + $this->fields[$offset] = $value; + } + + /** + * ArrayAccess implementation + */ + public function offsetExists($offset): bool + { + return isset($this->fields[$offset]); + } + + /** + * ArrayAccess implementation + */ + public function offsetUnset($offset): void + { + unset($this->fields[$offset]); + } + + /** + * ArrayAccess implementation + */ + public function offsetGet($offset): mixed + { + return $this->fields[$offset] ?? null; + } +} diff --git a/modules/backend/classes/FormWidgetBase.php b/modules/backend/classes/FormWidgetBase.php new file mode 100644 index 0000000..9d06e12 --- /dev/null +++ b/modules/backend/classes/FormWidgetBase.php @@ -0,0 +1,152 @@ +formField = $formField; + $this->fieldName = $formField->fieldName; + $this->valueFrom = $formField->valueFrom; + + $this->config = $this->makeConfig($configuration); + + $this->fillFromConfig([ + 'model', + 'data', + 'sessionKey', + 'previewMode', + 'showLabels', + 'parentForm', + ]); + + parent::__construct($controller, $configuration); + } + + /** + * Retrieve the parent form for this formwidget + * + * @return Backend\Widgets\Form|null + */ + public function getParentForm() + { + return $this->parentForm; + } + + /** + * Returns the HTML element field name for this widget, used for capturing + * user input, passed back to the getSaveValue method when saving. + * @return string HTML element name + */ + public function getFieldName() + { + return $this->formField->getName(); + } + + /** + * Returns a unique ID for this widget. Useful in creating HTML markup. + */ + public function getId($suffix = null) + { + $id = parent::getId($suffix); + $id .= '-' . $this->fieldName; + return HtmlHelper::nameToId($id); + } + + /** + * Process the postback value for this widget. If the value is omitted from + * postback data, it will be NULL, otherwise it will be an empty string. + * @param mixed $value The existing value for this widget. + * @return string The new value for this widget. + */ + public function getSaveValue($value) + { + return $value; + } + + /** + * Returns the value for this form field, + * supports nesting via HTML array. + * @return string + */ + public function getLoadValue() + { + if ($this->formField->value !== null) { + return $this->formField->value; + } + + $defaultValue = !$this->model->exists + ? $this->formField->getDefaultFromData($this->data ?: $this->model) + : null; + + return $this->formField->getValueFromData($this->data ?: $this->model, $defaultValue); + } +} diff --git a/modules/backend/classes/ListColumn.php b/modules/backend/classes/ListColumn.php new file mode 100644 index 0000000..04bc867 --- /dev/null +++ b/modules/backend/classes/ListColumn.php @@ -0,0 +1,291 @@ +columnName = $columnName; + $this->label = $label; + } + + /** + * Specifies a list column rendering mode. Supported modes are: + * - text - text column, aligned left + * - number - numeric column, aligned right + * @param string $type Specifies a render mode as described above + */ + public function displayAs($type, $config) + { + $this->type = strtolower($type) ?: $this->type; + $this->config = $this->evalConfig($config); + return $this; + } + + /** + * Process options and apply them to this object. + * @param array $config + * @return array + */ + protected function evalConfig($config) + { + if (isset($config['width'])) { + $this->width = $config['width']; + } + if (isset($config['cssClass'])) { + $this->cssClass = $config['cssClass']; + } + if (isset($config['headCssClass'])) { + $this->headCssClass = $config['headCssClass']; + } + if (isset($config['searchable'])) { + $this->searchable = $config['searchable']; + } + if (isset($config['sortable'])) { + $this->sortable = $config['sortable']; + } + if (isset($config['summable'])) { + $this->summable = $config['summable']; + } + if (isset($config['clickable'])) { + $this->clickable = $config['clickable']; + } + if (isset($config['invisible'])) { + $this->invisible = $config['invisible']; + } + if (isset($config['valueFrom'])) { + $this->valueFrom = $config['valueFrom']; + } + if (isset($config['default'])) { + $this->defaults = $config['default']; + } + if (isset($config['select'])) { + $this->sqlSelect = $config['select']; + } + if (isset($config['relation'])) { + $this->relation = $config['relation']; + } + if (isset($config['format'])) { + $this->format = $config['format']; + } + if (isset($config['path'])) { + $this->path = $config['path']; + } + if (isset($config['align']) && \in_array($config['align'], ['left', 'right', 'center'])) { + $this->align = $config['align']; + } + + return $config; + } + + /** + * Returns a HTML valid name for the column name. + * @return string + */ + public function getName() + { + return HtmlHelper::nameToId($this->columnName); + } + + /** + * Returns a value suitable for the column id property. + * @param string $suffix Specify a suffix string + * @return string + */ + public function getId($suffix = null) + { + $id = 'column'; + + $id .= '-'.$this->columnName; + + if ($suffix) { + $id .= '-'.$suffix; + } + + return HtmlHelper::nameToId($id); + } + + /** + * Returns the column specific aligment css class. + * @return string + */ + public function getAlignClass() + { + return $this->align ? 'list-cell-align-' . $this->align : ''; + } + + /** + * Returns a raw config item value. + * @param string $value + * @param string $default + * @return mixed + */ + public function getConfig($value, $default = null) + { + return array_get($this->config, $value, $default); + } + + /** + * Returns this columns value from a supplied data set, which can be + * an array or a model or another generic collection. + * @param mixed $data + * @param mixed $default + * @return mixed + */ + public function getValueFromData($data, $default = null) + { + $columnName = $this->valueFrom ?: $this->columnName; + return $this->getColumnNameFromData($columnName, $data, $default); + } + + /** + * Internal method to extract the value of a column name from a data set. + * @param string $columnName + * @param mixed $data + * @param mixed $default + * @return mixed + */ + protected function getColumnNameFromData($columnName, $data, $default = null) + { + /* + * Array column name, eg: column[key][key2][key3] + */ + $keyParts = HtmlHelper::nameToArray($columnName); + $result = $data; + + /* + * Loop the column key parts and build a value. + * To support relations only the last column should return the + * relation value, all others will look up the relation object as normal. + */ + foreach ($keyParts as $key) { + if ($result instanceof Model && $result->hasRelation($key)) { + $result = $result->{$key}; + } + else { + if (is_array($result) && array_key_exists($key, $result)) { + $result = $result[$key]; + } elseif (!isset($result->{$key})) { + return $default; + } else { + $result = $result->{$key}; + } + } + } + + return $result; + } +} diff --git a/modules/backend/classes/MainMenuItem.php b/modules/backend/classes/MainMenuItem.php new file mode 100644 index 0000000..ef64f56 --- /dev/null +++ b/modules/backend/classes/MainMenuItem.php @@ -0,0 +1,131 @@ +permissions[$permission] = $definition; + } + + /** + * @param SideMenuItem $sideMenu + */ + public function addSideMenuItem(SideMenuItem $sideMenu) + { + $this->sideMenu[$sideMenu->code] = $sideMenu; + } + + /** + * @param string $code + * @return SideMenuItem + * @throws SystemException + */ + public function getSideMenuItem(string $code) + { + if (!array_key_exists($code, $this->sideMenu)) { + throw new SystemException('No sidenavigation item available with code ' . $code); + } + + return $this->sideMenu[$code]; + } + + /** + * @param string $code + */ + public function removeSideMenuItem(string $code) + { + unset($this->sideMenu[$code]); + } + + /** + * @param array $data + * @return static + */ + public static function createFromArray(array $data) + { + $instance = new static(); + $instance->code = $data['code']; + $instance->owner = $data['owner']; + $instance->label = $data['label']; + $instance->url = $data['url']; + $instance->icon = $data['icon'] ?? null; + $instance->iconSvg = $data['iconSvg'] ?? null; + $instance->counter = $data['counter'] ?? null; + $instance->counterLabel = $data['counterLabel'] ?? null; + $instance->badge = $data['badge'] ?? null; + $instance->permissions = $data['permissions'] ?? $instance->permissions; + $instance->order = (!empty($data['order']) || @$data['order'] === 0) ? (int) $data['order'] : $instance->order; + return $instance; + } +} diff --git a/modules/backend/classes/NavigationManager.php b/modules/backend/classes/NavigationManager.php new file mode 100644 index 0000000..d06d7db --- /dev/null +++ b/modules/backend/classes/NavigationManager.php @@ -0,0 +1,796 @@ + 'Real.Owner'] + */ + protected $aliases = []; + + /** + * @var MainMenuItem[] List of registered items. + */ + protected $items; + + /** + * @var QuickActionItem[] List of registered quick actions. + */ + protected $quickActions; + + protected $contextSidenavPartials = []; + + protected $contextOwner; + protected $contextMainMenuItemCode; + protected $contextSideMenuItemCode; + + /** + * @var PluginManager + */ + protected $pluginManager; + + /** + * Initialize this singleton. + */ + protected function init() + { + foreach (static::$lazyAliases as $alias => $owner) { + $this->registerOwnerAlias($owner, $alias); + } + $this->pluginManager = PluginManager::instance(); + } + + /** + * Loads the menu items from modules and plugins + * @return void + * @throws SystemException + */ + protected function loadItems() + { + $this->items = []; + $this->quickActions = []; + + /* + * Load module items + */ + foreach ($this->callbacks as $callback) { + $callback($this); + } + + /* + * Load plugin items + */ + $plugins = $this->pluginManager->getPlugins(); + + foreach ($plugins as $id => $plugin) { + $items = $plugin->registerNavigation(); + $quickActions = $plugin->registerQuickActions(); + + if (!is_array($items) && !is_array($quickActions)) { + continue; + } + + if (is_array($items)) { + $this->registerMenuItems($id, $items); + } + if (is_array($quickActions)) { + $this->registerQuickActions($id, $quickActions); + } + } + + /** + * @event backend.menu.extendItems + * Provides an opportunity to manipulate the backend navigation + * + * Example usage: + * + * Event::listen('backend.menu.extendItems', function ((\Backend\Classes\NavigationManager) $navigationManager) { + * $navigationManager->addMainMenuItems(...) + * $navigationManager->addSideMenuItems(...) + * $navigationManager->removeMainMenuItem(...) + * }); + * + */ + Event::fire('backend.menu.extendItems', [$this]); + + /* + * Sort menu items and quick actions + */ + $this->applyDefaultOrders($this->items); + uasort($this->items, static function ($a, $b) { + return $a->order - $b->order; + }); + $this->applyDefaultOrders($this->quickActions); + uasort($this->quickActions, static function ($a, $b) { + return $a->order - $b->order; + }); + + /* + * Filter items and quick actions that the user lacks permission for + */ + $user = BackendAuth::getUser(); + $this->items = $this->filterItemPermissions($user, $this->items); + $this->quickActions = $this->filterItemPermissions($user, $this->quickActions); + + foreach ($this->items as $item) { + if (!$item->sideMenu || !count($item->sideMenu)) { + continue; + } + + $this->applyDefaultOrders($item->sideMenu); + + /* + * Sort side menu items + */ + uasort($item->sideMenu, static function ($a, $b) { + return $a->order - $b->order; + }); + + /* + * Filter items user lacks permission for + */ + $item->sideMenu = $this->filterItemPermissions($user, $item->sideMenu); + } + } + + /** + * Apply incremental default orders to items with the explicit auto-order value (-1) + * or that have invalid order values (non-integer). + * + * @param array $items Array of MainMenuItem, SideMenuItem, or QuickActionItem objects + * @return void + */ + protected function applyDefaultOrders(array $items) + { + $orderCount = 0; + foreach ($items as $item) { + if ($item->order !== -1 && is_integer($item->order)) { + continue; + } + $item->order = ($orderCount += 100); + } + } + + /** + * Registers a callback function that defines menu items. + * The callback function should register menu items by calling the manager's + * `registerMenuItems` method. The manager instance is passed to the callback + * function as an argument. Usage: + * + * BackendMenu::registerCallback(function ($manager) { + * $manager->registerMenuItems([...]); + * }); + * + * @param callable $callback A callable function. + */ + public function registerCallback(callable $callback) + { + $this->callbacks[] = $callback; + } + + /** + * Registers the back-end menu items. + * The argument is an array of the main menu items. The array keys represent the + * menu item codes, specific for the plugin/module. Each element in the + * array should be an associative array with the following keys: + * - label - specifies the menu label localization string key, required. + * - icon - an icon name from the Font Awesome icon collection, required. + * - url - the back-end relative URL the menu item should point to, required. + * - permissions - an array of permissions the back-end user should have, optional. + * The item will be displayed if the user has any of the specified permissions. + * - order - a position of the item in the menu, optional. + * - counter - an optional numeric value to output near the menu icon. The value should be + * a number or a callable returning a number. + * - counterLabel - an optional string value to describe the numeric reference in counter. + * - sideMenu - an array of side menu items, optional. If provided, the array items + * should represent the side menu item code, and each value should be an associative + * array with the following keys: + * - label - specifies the menu label localization string key, required. + * - icon - an icon name from the Font Awesome icon collection, required. + * - url - the back-end relative URL the menu item should point to, required. + * - attributes - an array of attributes and values to apply to the menu item, optional. + * - permissions - an array of permissions the back-end user should have, optional. + * - counter - an optional numeric value to output near the menu icon. The value should be + * a number or a callable returning a number. + * - counterLabel - an optional string value to describe the numeric reference in counter. + * - badge - an optional string value to output near the menu icon. The value should be + * a string. This value will override the counter if set. + * @param string $owner Specifies the menu items owner plugin or module in the format Author.Plugin. + * @param array $definitions An array of the menu item definitions. + * @throws SystemException + */ + public function registerMenuItems($owner, array $definitions) + { + $validator = Validator::make($definitions, [ + '*.label' => 'required', + '*.icon' => 'required_without:*.iconSvg', + '*.url' => 'required', + '*.sideMenu.*.label' => 'nullable|required', + '*.sideMenu.*.icon' => 'nullable|required_without:*.sideMenu.*.iconSvg', + '*.sideMenu.*.url' => 'nullable|required', + ]); + + if ($validator->fails()) { + $errorMessage = 'Invalid menu item detected in ' . $owner . '. Contact the plugin author to fix (' . $validator->errors()->first() . ')'; + if (Config::get('app.debug', false)) { + throw new SystemException($errorMessage); + } + + Log::error($errorMessage); + } + + $this->addMainMenuItems($owner, $definitions); + } + + /** + * Register an owner alias + * + * @param string $owner The owner to register an alias for. Example: Real.Owner + * @param string $alias The alias to register. Example: Aliased.Owner + * @return void + */ + public function registerOwnerAlias(string $owner, string $alias) + { + $this->aliases[strtoupper($alias)] = strtoupper($owner); + } + + /** + * Dynamically add an array of main menu items + * @param string $owner + * @param array $definitions + */ + public function addMainMenuItems($owner, array $definitions) + { + foreach ($definitions as $code => $definition) { + $this->addMainMenuItem($owner, $code, $definition); + } + } + + /** + * Dynamically add a single main menu item + * @param string $owner + * @param string $code + * @param array $definition + */ + public function addMainMenuItem($owner, $code, array $definition) + { + $itemKey = $this->makeItemKey($owner, $code); + + if (isset($this->items[$itemKey])) { + $definition = array_merge((array) $this->items[$itemKey], $definition); + } + + $item = array_merge($definition, [ + 'code' => $code, + 'owner' => $owner + ]); + + $this->items[$itemKey] = MainMenuItem::createFromArray($item); + + if (array_key_exists('sideMenu', $item)) { + $this->addSideMenuItems($owner, $code, $item['sideMenu']); + } + } + + /** + * @param string $owner + * @param string $code + * @return MainMenuItem + * @throws SystemException + */ + public function getMainMenuItem(string $owner, string $code) + { + $itemKey = $this->makeItemKey($owner, $code); + + if (!array_key_exists($itemKey, $this->items)) { + throw new SystemException('No main menu item found with key ' . $itemKey); + } + + return $this->items[$itemKey]; + } + + /** + * Removes a single main menu item + * @param $owner + * @param $code + */ + public function removeMainMenuItem($owner, $code) + { + $itemKey = $this->makeItemKey($owner, $code); + unset($this->items[$itemKey]); + } + + /** + * Dynamically add an array of side menu items + * @param string $owner + * @param string $code + * @param array $definitions + */ + public function addSideMenuItems($owner, $code, array $definitions) + { + foreach ($definitions as $sideCode => $definition) { + $this->addSideMenuItem($owner, $code, $sideCode, (array) $definition); + } + } + + /** + * Dynamically add a single side menu item + * @param string $owner + * @param string $code + * @param string $sideCode + * @param array $definition + * @return bool + */ + public function addSideMenuItem($owner, $code, $sideCode, array $definition) + { + $itemKey = $this->makeItemKey($owner, $code); + + if (!isset($this->items[$itemKey])) { + return false; + } + + $mainItem = $this->items[$itemKey]; + + $definition = array_merge($definition, [ + 'code' => $sideCode, + 'owner' => $owner + ]); + + if (isset($mainItem->sideMenu[$sideCode])) { + $definition = array_merge((array) $mainItem->sideMenu[$sideCode], $definition); + } + + $item = SideMenuItem::createFromArray($definition); + + $this->items[$itemKey]->addSideMenuItem($item); + return true; + } + + /** + * Remove multiple side menu items + * + * @param string $owner + * @param string $code + * @param array $sideCodes + * @return void + */ + public function removeSideMenuItems($owner, $code, $sideCodes) + { + foreach ($sideCodes as $sideCode) { + $this->removeSideMenuItem($owner, $code, $sideCode); + } + } + + /** + * Removes a single main menu item + * @param string $owner + * @param string $code + * @param string $sideCode + * @return bool + */ + public function removeSideMenuItem($owner, $code, $sideCode) + { + $itemKey = $this->makeItemKey($owner, $code); + if (!isset($this->items[$itemKey])) { + return false; + } + + $mainItem = $this->items[$itemKey]; + $mainItem->removeSideMenuItem($sideCode); + return true; + } + + /** + * Returns a list of the main menu items. + * @return array + * @throws SystemException + */ + public function listMainMenuItems() + { + if ($this->items === null && $this->quickActions === null) { + $this->loadItems(); + } + + if ($this->items === null) { + return []; + } + + foreach ($this->items as $item) { + if ($item->badge) { + $item->counter = (string) $item->badge; + continue; + } + if ($item->counter === false) { + continue; + } + + if ($item->counter !== null && is_callable($item->counter)) { + $item->counter = call_user_func($item->counter, $item); + } elseif (!empty((int) $item->counter)) { + $item->counter = (int) $item->counter; + } elseif (!empty($sideItems = $this->listSideMenuItems($item->owner, $item->code))) { + $item->counter = 0; + foreach ($sideItems as $sideItem) { + if ($sideItem->badge) { + continue; + } + $item->counter += $sideItem->counter; + } + } + + if (empty($item->counter) || !is_numeric($item->counter)) { + $item->counter = null; + } + } + + return $this->items; + } + + /** + * Returns a list of side menu items for the currently active main menu item. + * The currently active main menu item is set with the setContext methods. + * @param null $owner + * @param null $code + * @return SideMenuItem[] + * @throws SystemException + */ + public function listSideMenuItems($owner = null, $code = null) + { + $activeItem = null; + + if ($owner !== null && $code !== null) { + $activeItem = @$this->items[$this->makeItemKey($owner, $code)]; + } else { + foreach ($this->listMainMenuItems() as $item) { + if ($this->isMainMenuItemActive($item)) { + $activeItem = $item; + break; + } + } + } + + if (!$activeItem) { + return []; + } + + $items = $activeItem->sideMenu; + + foreach ($items as $item) { + if ($item->badge) { + $item->counter = (string) $item->badge; + continue; + } + if ($item->counter !== null && is_callable($item->counter)) { + $item->counter = call_user_func($item->counter, $item); + if (empty($item->counter)) { + $item->counter = null; + } + } + if (!is_null($item->counter) && !is_numeric($item->counter)) { + throw new SystemException("The menu item {$activeItem->code}.{$item->code}'s counter property is invalid. Check to make sure it's numeric or callable. Value: " . var_export($item->counter, true)); + } + } + + return $items; + } + + /** + * Registers quick actions in the main navigation. + * + * Quick actions are single purpose links displayed to the left of the user menu in the + * backend main navigation. + * + * The argument is an array of the quick action items. The array keys represent the + * quick action item codes, specific for the plugin/module. Each element in the + * array should be an associative array with the following keys: + * - label - specifies the action label localization string key, used as a tooltip, required. + * - icon - an icon name from the Font Awesome icon collection, required if iconSvg is unspecified. + * - iconSvg - a custom SVG icon to use for the icon, required if icon is unspecified. + * - url - the back-end relative URL the quick action item should point to, required. + * - permissions - an array of permissions the back-end user should have, optional. + * The item will be displayed if the user has any of the specified permissions. + * - order - a position of the item in the menu, optional. + * + * @param string $owner Specifies the quick action items owner plugin or module in the format Author.Plugin. + * @param array $definitions An array of the quick action item definitions. + * @return void + * @throws SystemException If the validation of the quick action configuration fails + */ + public function registerQuickActions($owner, array $definitions) + { + $validator = Validator::make($definitions, [ + '*.label' => 'required', + '*.icon' => 'required_without:*.iconSvg', + '*.url' => 'required' + ]); + + if ($validator->fails()) { + $errorMessage = 'Invalid quick action item detected in ' . $owner . '. Contact the plugin author to fix (' . $validator->errors()->first() . ')'; + if (Config::get('app.debug', false)) { + throw new SystemException($errorMessage); + } + + Log::error($errorMessage); + } + + $this->addQuickActionItems($owner, $definitions); + } + + /** + * Dynamically add an array of quick action items + * + * @param string $owner + * @param array $definitions + * @return void + */ + public function addQuickActionItems($owner, array $definitions) + { + foreach ($definitions as $code => $definition) { + $this->addQuickActionItem($owner, $code, $definition); + } + } + + /** + * Dynamically add a single quick action item + * + * @param string $owner + * @param string $code + * @param array $definition + * @return void + */ + public function addQuickActionItem($owner, $code, array $definition) + { + $itemKey = $this->makeItemKey($owner, $code); + + if (isset($this->quickActions[$itemKey])) { + $definition = array_merge((array) $this->quickActions[$itemKey], $definition); + } + + $item = array_merge($definition, [ + 'code' => $code, + 'owner' => $owner + ]); + + $this->quickActions[$itemKey] = QuickActionItem::createFromArray($item); + } + + /** + * Gets the instance of a specified quick action item. + * + * @param string $owner + * @param string $code + * @return QuickActionItem + * @throws SystemException + */ + public function getQuickActionItem(string $owner, string $code) + { + $itemKey = $this->makeItemKey($owner, $code); + + if (!array_key_exists($itemKey, $this->quickActions)) { + throw new SystemException('No quick action item found with key ' . $itemKey); + } + + return $this->quickActions[$itemKey]; + } + + /** + * Removes a single quick action item + * + * @param $owner + * @param $code + * @return void + */ + public function removeQuickActionItem($owner, $code) + { + $itemKey = $this->makeItemKey($owner, $code); + unset($this->quickActions[$itemKey]); + } + + /** + * Returns a list of quick action items. + * + * @return array + * @throws SystemException + */ + public function listQuickActionItems() + { + if ($this->items === null && $this->quickActions === null) { + $this->loadItems(); + } + + if ($this->quickActions === null) { + return []; + } + + return $this->quickActions; + } + + /** + * Sets the navigation context. + * The function sets the navigation owner, main menu item code and the side menu item code. + * @param string $owner Specifies the navigation owner in the format Vendor/Module + * @param string $mainMenuItemCode Specifies the main menu item code + * @param string $sideMenuItemCode Specifies the side menu item code + */ + public function setContext($owner, $mainMenuItemCode, $sideMenuItemCode = null) + { + $this->setContextOwner($owner); + $this->setContextMainMenu($mainMenuItemCode); + $this->setContextSideMenu($sideMenuItemCode); + } + + /** + * Sets the navigation context owner. + * + * @param string $owner Specifies the navigation owner in the format Vendor/Module + */ + public function setContextOwner($owner) + { + $this->contextOwner = strtoupper($owner); + } + + /** + * Gets the navigation context owner + */ + public function getContextOwner() + { + return $this->aliases[$this->contextOwner] ?? $this->contextOwner; + } + + /** + * Specifies a code of the main menu item in the current navigation context. + * @param string $mainMenuItemCode Specifies the main menu item code + */ + public function setContextMainMenu($mainMenuItemCode) + { + $this->contextMainMenuItemCode = $mainMenuItemCode; + } + + /** + * Returns information about the current navigation context. + * @return mixed Returns an object with the following fields: + * - mainMenuCode + * - sideMenuCode + * - owner + */ + public function getContext() + { + return (object)[ + 'mainMenuCode' => $this->contextMainMenuItemCode, + 'sideMenuCode' => $this->contextSideMenuItemCode, + 'owner' => $this->getContextOwner(), + ]; + } + + /** + * Specifies a code of the side menu item in the current navigation context. + * If the code is set to TRUE, the first item will be flagged as active. + * @param string $sideMenuItemCode Specifies the side menu item code + */ + public function setContextSideMenu($sideMenuItemCode) + { + $this->contextSideMenuItemCode = $sideMenuItemCode; + } + + /** + * Determines if a main menu item is active. + * @param MainMenuItem $item Specifies the item object. + * @return boolean Returns true if the menu item is active. + */ + public function isMainMenuItemActive($item) + { + return $this->getContextOwner() === strtoupper($item->owner) && $this->contextMainMenuItemCode === $item->code; + } + + /** + * Returns the currently active main menu item + * @return null|MainMenuItem $item Returns the item object or null. + * @throws SystemException + */ + public function getActiveMainMenuItem() + { + foreach ($this->listMainMenuItems() as $item) { + if ($this->isMainMenuItemActive($item)) { + return $item; + } + } + + return null; + } + + /** + * Determines if a side menu item is active. + * @param SideMenuItem $item Specifies the item object. + * @return boolean Returns true if the side item is active. + */ + public function isSideMenuItemActive($item) + { + if ($this->contextSideMenuItemCode === true) { + $this->contextSideMenuItemCode = null; + return true; + } + + return $this->getContextOwner() === strtoupper($item->owner) && $this->contextSideMenuItemCode === $item->code; + } + + /** + * Registers a special side navigation partial for a specific main menu. + * The sidenav partial replaces the standard side navigation. + * @param string $owner Specifies the navigation owner in the format Vendor/Module. + * @param string $mainMenuItemCode Specifies the main menu item code. + * @param string $partial Specifies the partial name. + */ + public function registerContextSidenavPartial($owner, $mainMenuItemCode, $partial) + { + $this->contextSidenavPartials[$this->makeItemKey($owner, $mainMenuItemCode)] = $partial; + } + + /** + * Returns the side navigation partial for a specific main menu previously registered + * with the registerContextSidenavPartial() method. + * + * @param string $owner Specifies the navigation owner in the format Vendor/Module. + * @param string $mainMenuItemCode Specifies the main menu item code. + * @return mixed Returns the partial name or null. + */ + public function getContextSidenavPartial($owner, $mainMenuItemCode) + { + return $this->contextSidenavPartials[$this->makeItemKey($owner, $mainMenuItemCode)] ?? null; + } + + /** + * Removes menu items from an array if the supplied user lacks permission. + * @param \Backend\Models\User $user A user object + * @param MainMenuItem[]|SideMenuItem[] $items A collection of menu items + * @return array The filtered menu items + */ + protected function filterItemPermissions($user, array $items) + { + if (!$user) { + return $items; + } + + $items = array_filter($items, static function ($item) use ($user) { + if (!$item->permissions || !count($item->permissions)) { + return true; + } + + return $user->hasAnyAccess($item->permissions); + }); + + return $items; + } + + /** + * Internal method to make a unique key for an item. + * @param string $owner + * @param string $code + * @return string + */ + protected function makeItemKey($owner, $code) + { + $owner = strtoupper($owner); + return ($this->aliases[$owner] ?? $owner) . '.' . strtoupper($code); + } +} diff --git a/modules/backend/classes/QuickActionItem.php b/modules/backend/classes/QuickActionItem.php new file mode 100644 index 0000000..8dab2e7 --- /dev/null +++ b/modules/backend/classes/QuickActionItem.php @@ -0,0 +1,105 @@ +attributes[$attribute] = $value; + } + + public function removeAttribute($attribute) + { + unset($this->attributes[$attribute]); + } + + /** + * @param string $permission + * @param array $definition + */ + public function addPermission(string $permission, array $definition) + { + $this->permissions[$permission] = $definition; + } + + /** + * @param string $permission + * @return void + */ + public function removePermission(string $permission) + { + unset($this->permissions[$permission]); + } + + /** + * @param array $data + * @return static + */ + public static function createFromArray(array $data) + { + $instance = new static(); + $instance->code = $data['code']; + $instance->owner = $data['owner']; + $instance->label = $data['label']; + $instance->url = $data['url']; + $instance->icon = $data['icon'] ?? null; + $instance->iconSvg = $data['iconSvg'] ?? null; + $instance->attributes = $data['attributes'] ?? $instance->attributes; + $instance->permissions = $data['permissions'] ?? $instance->permissions; + $instance->order = (!empty($data['order']) || @$data['order'] === 0) ? (int) $data['order'] : $instance->order; + return $instance; + } +} diff --git a/modules/backend/classes/ReportWidgetBase.php b/modules/backend/classes/ReportWidgetBase.php new file mode 100644 index 0000000..ac7b091 --- /dev/null +++ b/modules/backend/classes/ReportWidgetBase.php @@ -0,0 +1,28 @@ +properties = $this->validateProperties($properties); + + /* + * Ensure the provided alias (if present) takes effect as the widget configuration is + * not passed to the WidgetBase constructor which would normally take care of that + */ + if (!isset($this->alias)) { + $this->alias = $properties['alias'] ?? $this->defaultAlias; + } + + parent::__construct($controller); + } +} diff --git a/modules/backend/classes/SideMenuItem.php b/modules/backend/classes/SideMenuItem.php new file mode 100644 index 0000000..a7fd9b6 --- /dev/null +++ b/modules/backend/classes/SideMenuItem.php @@ -0,0 +1,123 @@ +attributes[$attribute] = $value; + } + + public function removeAttribute($attribute) + { + unset($this->attributes[$attribute]); + } + + /** + * @param string $permission + * @param array $definition + */ + public function addPermission(string $permission, array $definition) + { + $this->permissions[$permission] = $definition; + } + + /** + * @param string $permission + * @return void + */ + public function removePermission(string $permission) + { + unset($this->permissions[$permission]); + } + + /** + * @param array $data + * @return static + */ + public static function createFromArray(array $data) + { + $instance = new static(); + $instance->code = $data['code']; + $instance->owner = $data['owner']; + $instance->label = $data['label']; + $instance->url = $data['url']; + $instance->icon = $data['icon'] ?? null; + $instance->iconSvg = $data['iconSvg'] ?? null; + $instance->counter = $data['counter'] ?? null; + $instance->counterLabel = $data['counterLabel'] ?? null; + $instance->attributes = $data['attributes'] ?? $instance->attributes; + $instance->badge = $data['badge'] ?? null; + $instance->permissions = $data['permissions'] ?? $instance->permissions; + $instance->order = (!empty($data['order']) || @$data['order'] === 0) ? (int) $data['order'] : $instance->order; + return $instance; + } +} diff --git a/modules/backend/classes/Skin.php b/modules/backend/classes/Skin.php new file mode 100644 index 0000000..b64b83c --- /dev/null +++ b/modules/backend/classes/Skin.php @@ -0,0 +1,111 @@ +defaultSkinPath = base_path() . '/modules/backend'; + + /* + * Guess the skin path + */ + $class = get_called_class(); + $classFolder = strtolower(class_basename($class)); + $classFile = realpath(dirname(File::fromClass($class))); + $this->skinPath = $classFile + ? $classFile . '/' . $classFolder + : $this->defaultSkinPath; + + $this->publicSkinPath = File::localToPublic($this->skinPath); + $this->defaultPublicSkinPath = File::localToPublic($this->defaultSkinPath); + } + + /** + * Looks up a path to a skin-based file, if it doesn't exist, the default path is used. + * @param string $path + * @param boolean $isPublic + * @return string + */ + public function getPath($path = null, $isPublic = false) + { + $path = RouterHelper::normalizeUrl($path); + $assetFile = $this->skinPath . $path; + + if (File::isFile($assetFile)) { + return $isPublic + ? $this->publicSkinPath . $path + : $this->skinPath . $path; + } + + return $isPublic + ? $this->defaultPublicSkinPath . $path + : $this->defaultSkinPath . $path; + } + + /** + * Returns an array of paths where skin layouts can be found. + * @return array + */ + public function getLayoutPaths() + { + return [$this->skinPath.'/layouts', $this->defaultSkinPath.'/layouts']; + } + + /** + * Returns the active skin. + */ + public static function getActive() + { + if (self::$skinCache !== null) { + return self::$skinCache; + } + + $skinClass = Config::get('cms.backendSkin'); + $skinObject = new $skinClass(); + return self::$skinCache = $skinObject; + } +} diff --git a/modules/backend/classes/WidgetBase.php b/modules/backend/classes/WidgetBase.php new file mode 100644 index 0000000..91f1ec5 --- /dev/null +++ b/modules/backend/classes/WidgetBase.php @@ -0,0 +1,216 @@ +controller = $controller; + $this->viewPath = $this->configPath = $this->guessViewPath('/partials'); + $this->assetPath = $this->guessViewPath('/assets', true); + + /* + * Apply configuration values to a new config object, if a parent + * constructor hasn't done it already. + */ + if ($this->config === null) { + $this->config = $this->makeConfig($configuration); + } + + /* + * If no alias is set by the configuration. + */ + if (!isset($this->alias)) { + $this->alias = $this->config->alias ?? $this->defaultAlias; + } + + /* + * Prepare assets used by this widget. + */ + $this->loadAssets(); + + parent::__construct(); + + /* + * Initialize the widget. + */ + if (!$this->getConfig('noInit', false)) { + $this->init(); + } + } + + /** + * Initialize the widget, called by the constructor and free from its parameters. + * @return void + */ + public function init() + { + } + + /** + * Renders the widget's primary contents. + * @return string HTML markup supplied by this widget. + */ + public function render() + { + } + + /** + * Adds widget specific asset files. Use $this->addJs() and $this->addCss() + * to register new assets to include on the page. + * @return void + */ + protected function loadAssets() + { + } + + /** + * Binds a widget to the controller for safe use. + * @return void + */ + public function bindToController() + { + if ($this->controller->widget === null) { + $this->controller->widget = new stdClass; + } + + $this->controller->widget->{$this->alias} = $this; + } + + /** + * Transfers config values stored inside the $config property directly + * on to the root object properties. If no properties are defined + * all config will be transferred if it finds a matching property. + * @param array $properties + * @return void + */ + protected function fillFromConfig($properties = null) + { + if ($properties === null) { + $properties = array_keys((array) $this->config); + } + + foreach ($properties as $property) { + if (property_exists($this, $property)) { + $this->{$property} = $this->getConfig($property, $this->{$property}); + } + } + } + + /** + * Returns a unique ID for this widget. Useful in creating HTML markup. + * @param string $suffix An extra string to append to the ID. + * @return string A unique identifier. + */ + public function getId($suffix = null) + { + $id = class_basename(get_called_class()); + + if ($this->alias != $this->defaultAlias) { + $id .= '-' . $this->alias; + } + + if ($suffix !== null) { + $id .= '-' . $suffix; + } + + return HtmlHelper::nameToId($id); + } + + /** + * Returns a fully qualified event handler name for this widget. + * @param string $name The ajax event handler name. + * @return string + */ + public function getEventHandler($name) + { + return $this->alias . '::' . $name; + } + + /** + * Safe accessor for configuration values. + * @param string $name Config name, supports array names like "field[key]" + * @param string $default Default value if nothing is found + * @return string + */ + public function getConfig($name, $default = null) + { + /* + * Array field name, eg: field[key][key2][key3] + */ + $keyParts = HtmlHelper::nameToArray($name); + + /* + * First part will be the field name, pop it off + */ + $fieldName = array_shift($keyParts); + if (!isset($this->config->{$fieldName})) { + return $default; + } + + $result = $this->config->{$fieldName}; + + /* + * Loop the remaining key parts and build a result + */ + foreach ($keyParts as $key) { + if (!array_key_exists($key, $result)) { + return $default; + } + + $result = $result[$key]; + } + + return $result; + } + + /** + * Returns the controller using this widget. + */ + public function getController() + { + return $this->controller; + } +} diff --git a/modules/backend/classes/WidgetManager.php b/modules/backend/classes/WidgetManager.php new file mode 100644 index 0000000..302ef4b --- /dev/null +++ b/modules/backend/classes/WidgetManager.php @@ -0,0 +1,268 @@ + $formWidgetInfo]. + */ + protected $formWidgets; + + /** + * @var array Cache of form widget registration callbacks. + */ + protected $formWidgetCallbacks = []; + + /** + * @var array An array of form widgets keyed by their code. Stored in the form of ['formwidgetcode' => 'FormWidgetClass']. + */ + protected $formWidgetHints; + + /** + * @var array An array of report widgets. + */ + protected $reportWidgets; + + /** + * @var array Cache of report widget registration callbacks. + */ + protected $reportWidgetCallbacks = []; + + /** + * @var System\Classes\PluginManager + */ + protected $pluginManager; + + /** + * Initialize this singleton. + */ + protected function init() + { + $this->pluginManager = PluginManager::instance(); + } + + // + // Form Widgets + // + + /** + * Returns a list of registered form widgets. + * @return array Array keys are class names. + */ + public function listFormWidgets() + { + if ($this->formWidgets === null) { + $this->formWidgets = []; + + /* + * Load module widgets + */ + foreach ($this->formWidgetCallbacks as $callback) { + $callback($this); + } + + /* + * Load plugin widgets + */ + $plugins = $this->pluginManager->getPlugins(); + + foreach ($plugins as $plugin) { + if (!is_array($widgets = $plugin->registerFormWidgets())) { + continue; + } + + foreach ($widgets as $className => $widgetInfo) { + $this->registerFormWidget($className, $widgetInfo); + } + } + } + + return $this->formWidgets; + } + + /** + * Registers a single form widget. + * @param string $className Widget class name. + * @param array $widgetInfo Registration information, can contain a `code` key. + * @return void + */ + public function registerFormWidget($className, $widgetInfo = null) + { + if (!is_array($widgetInfo)) { + $widgetInfo = ['code' => $widgetInfo]; + } + + $widgetCode = $widgetInfo['code'] ?? null; + + if (!$widgetCode) { + $widgetCode = Str::getClassId($className); + } + + $this->formWidgets[$className] = $widgetInfo; + $this->formWidgetHints[$widgetCode] = $className; + } + + /** + * Manually registers form widget for consideration. Usage: + * + * WidgetManager::registerFormWidgets(function ($manager) { + * $manager->registerFormWidget('Backend\FormWidgets\CodeEditor', 'codeeditor'); + * }); + * + */ + public function registerFormWidgets(callable $definitions) + { + $this->formWidgetCallbacks[] = $definitions; + } + + /** + * Returns a class name from a form widget code + * Normalizes a class name or converts an code to its class name. + * @param string $name Class name or form widget code. + * @return string The class name resolved, or the original name. + */ + public function resolveFormWidget($name) + { + if ($this->formWidgets === null) { + $this->listFormWidgets(); + } + + $hints = $this->formWidgetHints; + + if (isset($hints[$name])) { + return $hints[$name]; + } + + $_name = Str::normalizeClassName($name); + if (isset($this->formWidgets[$_name])) { + return $_name; + } + + return $name; + } + + // + // Report Widgets + // + + /** + * Returns a list of registered report widgets. + * @return array Array keys are class names. + */ + public function listReportWidgets() + { + if ($this->reportWidgets === null) { + $this->reportWidgets = []; + + /* + * Load module widgets + */ + foreach ($this->reportWidgetCallbacks as $callback) { + $callback($this); + } + + /* + * Load plugin widgets + */ + $plugins = $this->pluginManager->getPlugins(); + + foreach ($plugins as $plugin) { + if (!is_array($widgets = $plugin->registerReportWidgets())) { + continue; + } + + foreach ($widgets as $className => $widgetInfo) { + $this->registerReportWidget($className, $widgetInfo); + } + } + } + + /** + * @event system.reportwidgets.extendItems + * Enables adding or removing report widgets. + * + * You will have access to the WidgetManager instance and be able to call the appropiate methods + * $manager->registerReportWidget(); + * $manager->removeReportWidget(); + * + * Example usage: + * + * Event::listen('system.reportwidgets.extendItems', function ($manager) { + * $manager->removeReportWidget('Acme\ReportWidgets\YourWidget'); + * }); + * + */ + Event::fire('system.reportwidgets.extendItems', [$this]); + + $user = BackendAuth::getUser(); + foreach ($this->reportWidgets as $widget => $config) { + if (!empty($config['permissions'])) { + if (!$user->hasAccess($config['permissions'], false)) { + unset($this->reportWidgets[$widget]); + } + } + } + + return $this->reportWidgets; + } + + /** + * Returns the raw array of registered report widgets. + * @return array Array keys are class names. + */ + public function getReportWidgets() + { + return $this->reportWidgets; + } + + /* + * Registers a single report widget. + */ + public function registerReportWidget($className, $widgetInfo) + { + $this->reportWidgets[$className] = $widgetInfo; + } + + /** + * Manually registers report widget for consideration. Usage: + * + * WidgetManager::registerReportWidgets(function ($manager) { + * $manager->registerReportWidget('Winter\GoogleAnalytics\ReportWidgets\TrafficOverview', [ + * 'name' => 'Google Analytics traffic overview', + * 'context' => 'dashboard' + * ]); + * }); + * + */ + public function registerReportWidgets(callable $definitions) + { + $this->reportWidgetCallbacks[] = $definitions; + } + + /** + * Remove a registered ReportWidget. + * @param string $className Widget class name. + * @return void + */ + public function removeReportWidget($className) + { + if (!$this->reportWidgets) { + throw new SystemException('Unable to remove a widget before widgets are loaded.'); + } + + unset($this->reportWidgets[$className]); + } +} diff --git a/modules/backend/composer.json b/modules/backend/composer.json new file mode 100644 index 0000000..bb18309 --- /dev/null +++ b/modules/backend/composer.json @@ -0,0 +1,39 @@ +{ + "name": "winter/wn-backend-module", + "type": "winter-module", + "description": "Backend module for Winter CMS", + "homepage": "https://wintercms.com", + "keywords": ["winter cms", "winter", "backend"], + "license": "MIT", + "authors": [ + { + "name": "Alexey Bobkov", + "email": "aleksey.bobkov@gmail.com", + "role": "Original Author" + }, + { + "name": "Samuel Georges", + "email": "daftspunky@gmail.com", + "role": "Original Author" + }, + { + "name": "Luke Towers", + "email": "wintercms@luketowers.ca", + "role": "Lead Maintainer" + } + ], + "require": { + "php": ">=8.1", + "composer/installers": "~1.11.0", + "laravel/framework": "^9.1" + }, + "replace": { + "october/backend": "1.1.*" + }, + "autoload": { + "psr-4": { + "Backend\\": "" + } + }, + "minimum-stability": "dev" +} diff --git a/modules/backend/console/CreateController.php b/modules/backend/console/CreateController.php new file mode 100644 index 0000000..107e1a3 --- /dev/null +++ b/modules/backend/console/CreateController.php @@ -0,0 +1,119 @@ +(eg: Winter.Blog)} + {controller : The name of the controller to generate. (eg: Posts)} + {--stubs : Create view files for local overwrites.} + {--force : Overwrite existing files with generated files.} + {--model= : Defines the model name to use. If not provided, the singular name of the controller is used.} + {--l|layout=standard : Set the formLayout to use (standard, sidebar, fancy)} + {--uninspiring : Disable inspirational quotes} + '; + + /** + * @var string The console command description. + */ + protected $description = 'Creates a new controller.'; + + /** + * @var string The type of class being generated. + */ + protected $type = 'Controller'; + + /** + * @var string The argument that the generated class name comes from + */ + protected $nameFrom = 'controller'; + + /** + * @var bool Allows the process to continue if an existing file is detected + */ + protected bool $throwOverwriteException = false; + + /** + * @var array A mapping of stub to generated file. + */ + protected $stubs = [ + 'scaffold/controller/config_form.stub' => 'controllers/{{lower_name}}/config_form.yaml', + 'scaffold/controller/config_list.stub' => 'controllers/{{lower_name}}/config_list.yaml', + 'scaffold/controller/controller.stub' => 'controllers/{{studly_name}}.php', + ]; + + /** + * Prepare variables for stubs. + */ + protected function prepareVars(): array + { + $vars = parent::prepareVars(); + $layout = $this->option('layout'); + /* + * Determine the model name to use, + * either supplied or singular from the controller name. + */ + $model = $this->option('model'); + if (!$model) { + $model = Str::singular($vars['name']); + } + $vars['model'] = $model; + $vars['sidebar'] = $layout === 'sidebar'; + $vars['fancy'] = $layout === 'fancy'; + $vars['stubs'] = $this->option('stubs'); + + if ($this->option('stubs')) { + $this->stubs['scaffold/controller/index.stub'] = 'controllers/{{lower_name}}/index.php'; + $this->stubs['scaffold/controller/_list_toolbar.stub'] = 'controllers/{{lower_name}}/_list_toolbar.php'; + $this->stubs["scaffold/controller/{$layout}/create.stub"] = 'controllers/{{lower_name}}/create.php'; + $this->stubs["scaffold/controller/{$layout}/update.stub"] = 'controllers/{{lower_name}}/update.php'; + $this->stubs["scaffold/controller/{$layout}/preview.stub"] = 'controllers/{{lower_name}}/preview.php'; + + if ($layout === 'fancy') { + $this->stubs['scaffold/controller/fancy/_toolbar.stub'] = 'controllers/{{lower_name}}/_toolbar.php'; + } + } + + return $vars; + } + + /** + * Adds controller & model lang helpers to the vars + */ + protected function processVars($vars): array + { + $vars = parent::processVars($vars); + + $vars['controller_url'] = "{$vars['plugin_url']}/{$vars['lower_name']}"; + $vars['model_lang_key_short'] = "models.{$vars['lower_model']}"; + $vars['model_lang_key'] = "{$vars['plugin_id']}::lang.{$vars['model_lang_key_short']}"; + + return $vars; + } + + /** + * Gets the localization keys and values to be stored in the plugin's localization files + * Can reference $this->vars and $this->laravel->getLocale() internally + */ + protected function getLangKeys(): array + { + return [ + "{$this->vars['model_lang_key_short']}.label" => $this->vars['title_singular_name'], + "{$this->vars['model_lang_key_short']}.label_plural" => $this->vars['title_plural_name'], + ]; + } +} diff --git a/modules/backend/console/CreateFormWidget.php b/modules/backend/console/CreateFormWidget.php new file mode 100644 index 0000000..d5ba0f4 --- /dev/null +++ b/modules/backend/console/CreateFormWidget.php @@ -0,0 +1,56 @@ +(eg: Winter.Blog)} + {widget : The name of the form widget to generate. (eg: PostList)} + {--force : Overwrite existing files with generated files.} + {--uninspiring : Disable inspirational quotes} + '; + + /** + * The console command description. + * + * @var string + */ + protected $description = 'Creates a new form widget.'; + + /** + * The type of class being generated. + * + * @var string + */ + protected $type = 'FormWidget'; + + /** + * @var string The argument that the generated class name comes from + */ + protected $nameFrom = 'widget'; + + /** + * A mapping of stub to generated file. + * + * @var array + */ + protected $stubs = [ + 'scaffold/formwidget/formwidget.stub' => 'formwidgets/{{studly_name}}.php', + 'scaffold/formwidget/partial.stub' => 'formwidgets/{{lower_name}}/partials/_{{lower_name}}.php', + 'scaffold/formwidget/stylesheet.stub' => 'formwidgets/{{lower_name}}/assets/css/{{lower_name}}.css', + 'scaffold/formwidget/javascript.stub' => 'formwidgets/{{lower_name}}/assets/js/{{lower_name}}.js', + ]; +} diff --git a/modules/backend/console/CreateReportWidget.php b/modules/backend/console/CreateReportWidget.php new file mode 100644 index 0000000..33e329a --- /dev/null +++ b/modules/backend/console/CreateReportWidget.php @@ -0,0 +1,54 @@ +(eg: Winter.Blog)} + {widget : The name of the report widget to generate. (eg: PostViews)} + {--force : Overwrite existing files with generated files.} + {--uninspiring : Disable inspirational quotes} + '; + + /** + * The console command description. + * + * @var string + */ + protected $description = 'Creates a new report widget.'; + + /** + * The type of class being generated. + * + * @var string + */ + protected $type = 'ReportWidget'; + + /** + * @var string The argument that the generated class name comes from + */ + protected $nameFrom = 'widget'; + + /** + * A mapping of stub to generated file. + * + * @var array + */ + protected $stubs = [ + 'scaffold/reportwidget/reportwidget.stub' => 'reportwidgets/{{studly_name}}.php', + 'scaffold/reportwidget/widget.stub' => 'reportwidgets/{{lower_name}}/partials/_{{lower_name}}.php', + ]; +} diff --git a/modules/backend/console/UserCreate.php b/modules/backend/console/UserCreate.php new file mode 100644 index 0000000..b1ec787 --- /dev/null +++ b/modules/backend/console/UserCreate.php @@ -0,0 +1,87 @@ +Use the role\'s code} + {--f|force : Force the operation to run and ignore production warnings and confirmation questions.}'; + + /** + * @var string The console command description. + */ + protected $description = 'Creates a backend user.'; + + /** + * Execute the console command. + */ + public function handle(): int + { + $email = $this->argument('email'); + + if ( + Config::get('app.env', 'production') !== 'local' + && !$this->option('force') + && !$this->confirmWithInput("CAUTION, currently working with non-local data. Please confirm the user email address", $email) + ) { + return 1; + } + + if (User::where('email', $email)->exists()) { + $this->error('A user with that email already exists.'); + return 1; + } + + $data = [ + 'email' => $email, + 'password' => $this->option('password') ?: $this->secret('Password'), + 'first_name' => $this->option('fname') ?: $this->ask('First name', ''), + 'last_name' => $this->option('lname') ?: $this->ask('Last name', ''), + 'role_id' => ( + UserRole::where( + 'code', + $this->option('role') ?: $this->choice( + 'Role', + UserRole::lists('name', 'code') + ) + )->firstOrFail() + )->id, + ]; + + $data['password_confirmation'] = $data['password']; + + $user = User::create([ + 'first_name' => $data['first_name'], + 'last_name' => $data['last_name'], + 'login' => $data['email'], + 'email' => $data['email'], + 'role_id' => $data['role_id'], + 'password' => $data['password'], + 'password_confirmation' => $data['password'], + ]); + + $this->info("User {$user->email} created successfully with the {$role->name} role."); + + return 0; + } +} diff --git a/modules/backend/console/WinterPasswd.php b/modules/backend/console/WinterPasswd.php new file mode 100644 index 0000000..d6a96b2 --- /dev/null +++ b/modules/backend/console/WinterPasswd.php @@ -0,0 +1,135 @@ +(eg: admin or admin@example.com)} + {password? : The new password to set.} + '; + + /** + * @var string The console command description. + */ + protected $description = 'Change the password of a Backend user.'; + + /** + * @var array List of commands that this command replaces (aliases) + */ + protected $replaces = [ + 'october:passwd', + 'winter:password', + ]; + + /** + * @var bool Was the password automatically generated? + */ + protected $generatedPassword = false; + + /** + * Execute the console command. + * @return int + */ + public function handle() + { + $username = $this->argument('username') + ?? $this->ask('Username to reset'); + + // Check that the user exists + try { + $user = User::where('login', $username) + ->orWhere('email', $username) + ->firstOrFail(); + } catch (ModelNotFoundException $e) { + $this->error('The specified user does not exist.'); + return 1; + } + + $password = $this->argument('password') + ?? ( + $this->optionalSecret( + 'Enter new password (leave blank for generated password)', + false, + false + ) ?: $this->generatePassword() + ); + + // Change password + $user->password = $password; + $user->forceSave(); + + $this->info('Password successfully changed.'); + if ($this->generatedPassword) { + $this->output->writeLn('Password set to ' . $password . ''); + } + return 0; + } + + /** + * Return the 20 most recently updated users for autocompletion of the "username" argument + */ + public function suggestUsernameValues(): array + { + $options = []; + $users = User::orderBy('updated_at', 'desc')->limit(20)->get(); + foreach ($users as $user) { + if ($user->email) { + $options[] = $user->email; + } elseif ($user->username) { + $options[] = $user->username; + } + } + + return $options; + } + + /** + * Prompt the user for input but hide the answer from the console. + * + * Also allows for a default to be specified. + * + * @param string $question + * @param bool $fallback + * @return string + */ + protected function optionalSecret($question, $fallback = true, $default = null) + { + $question = new Question($question, $default); + + $question->setHidden(true)->setHiddenFallback($fallback); + + return $this->output->askQuestion($question); + } + + /** + * Generate a password and flag it as an automatically-generated password. + * + * @return string + */ + protected function generatePassword() + { + $this->generatedPassword = true; + + return Str::random(22); + } +} diff --git a/modules/backend/console/scaffold/controller/_list_toolbar.stub b/modules/backend/console/scaffold/controller/_list_toolbar.stub new file mode 100644 index 0000000..f062a1c --- /dev/null +++ b/modules/backend/console/scaffold/controller/_list_toolbar.stub @@ -0,0 +1,21 @@ + diff --git a/modules/backend/console/scaffold/controller/config_form.stub b/modules/backend/console/scaffold/controller/config_form.stub new file mode 100644 index 0000000..27320fc --- /dev/null +++ b/modules/backend/console/scaffold/controller/config_form.stub @@ -0,0 +1,31 @@ +# =================================== +# Form Behavior Config +# =================================== + +# Record name +name: '{{ model_lang_key }}.label' + +# Model Form Field configuration +form: $/{{ plugin_folder }}/models/{{ lower_model }}/fields.yaml + +# Model Class name +modelClass: {{ plugin_namespace }}\Models\{{ studly_model }} + +# Default redirect location +defaultRedirect: {{ controller_url }} + +# Create page +create: + title: backend::lang.form.create_title + redirect: {{ controller_url }}/update/:id + redirectClose: {{ controller_url }} + +# Update page +update: + title: backend::lang.form.update_title + redirect: {{ controller_url }} + redirectClose: {{ controller_url }} + +# Preview page +preview: + title: backend::lang.form.preview_title diff --git a/modules/backend/console/scaffold/controller/config_list.stub b/modules/backend/console/scaffold/controller/config_list.stub new file mode 100644 index 0000000..0725e06 --- /dev/null +++ b/modules/backend/console/scaffold/controller/config_list.stub @@ -0,0 +1,50 @@ +# =================================== +# List Behavior Config +# =================================== + +# Model List Column configuration +list: $/{{ plugin_folder }}/models/{{ lower_model }}/columns.yaml + +# Model Class name +modelClass: {{ plugin_namespace }}\Models\{{ studly_model }} + +# List Title +title: '{{ model_lang_key }}.label_plural' + +# Link URL for each record +recordUrl: {{ controller_url }}/update/:id + +# Message to display if the list is empty +noRecordsMessage: backend::lang.list.no_records + +# Records to display per page +recordsPerPage: 20 + +# Options to provide the user when selecting how many records to display per page +perPageOptions: [20, 40, 80, 100, 120] + +# Display page numbers with pagination, disable to improve performance +showPageNumbers: true + +# Displays the list column set up button +showSetup: true + +# Displays the sorting link on each column +showSorting: true + +# Default sorting column +# defaultSort: +# column: created_at +# direction: desc + +# Display checkboxes next to each record +showCheckboxes: true + +# Toolbar widget configuration +toolbar: + # Partial for toolbar buttons + buttons: list_toolbar + + # Search widget configuration + search: + prompt: backend::lang.list.search_prompt diff --git a/modules/backend/console/scaffold/controller/controller.stub b/modules/backend/console/scaffold/controller/controller.stub new file mode 100644 index 0000000..aacd5dc --- /dev/null +++ b/modules/backend/console/scaffold/controller/controller.stub @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + url): ?> + + + + + + + + + + + +
    diff --git a/modules/backend/console/scaffold/controller/fancy/create.stub b/modules/backend/console/scaffold/controller/fancy/create.stub new file mode 100644 index 0000000..0e7a77d --- /dev/null +++ b/modules/backend/console/scaffold/controller/fancy/create.stub @@ -0,0 +1,21 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> +
    + $this->formGetId(), + 'class' => 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => 'true', + ]) ?> +
    + formRender() ?> +
    + +
    + +

    fatalError) ?>

    +

    + diff --git a/modules/backend/console/scaffold/controller/fancy/preview.stub b/modules/backend/console/scaffold/controller/fancy/preview.stub new file mode 100644 index 0000000..5180edc --- /dev/null +++ b/modules/backend/console/scaffold/controller/fancy/preview.stub @@ -0,0 +1,17 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> + $this->formGetId(), + 'class' => 'layout', + ]) ?> +
    + formRenderPreview() ?> +
    + + +

    fatalError) ?>

    +

    + diff --git a/modules/backend/console/scaffold/controller/fancy/update.stub b/modules/backend/console/scaffold/controller/fancy/update.stub new file mode 100644 index 0000000..0e7a77d --- /dev/null +++ b/modules/backend/console/scaffold/controller/fancy/update.stub @@ -0,0 +1,21 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> +
    + $this->formGetId(), + 'class' => 'layout', + 'data-change-monitor' => 'true', + 'data-window-close-confirm' => 'true', + ]) ?> +
    + formRender() ?> +
    + +
    + +

    fatalError) ?>

    +

    + diff --git a/modules/backend/console/scaffold/controller/index.stub b/modules/backend/console/scaffold/controller/index.stub new file mode 100644 index 0000000..ea43a36 --- /dev/null +++ b/modules/backend/console/scaffold/controller/index.stub @@ -0,0 +1 @@ +listRender() ?> diff --git a/modules/backend/console/scaffold/controller/sidebar/create.stub b/modules/backend/console/scaffold/controller/sidebar/create.stub new file mode 100644 index 0000000..c367b04 --- /dev/null +++ b/modules/backend/console/scaffold/controller/sidebar/create.stub @@ -0,0 +1,39 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> + +
    +
    + formRenderOutsideFields() ?> + formRenderPrimaryTabs() ?> +
    + +
    + formMakePartial('toolbar') ?> +
    +
    + + + +
    formRenderSecondaryTabs() ?>
    + + + + $this->formGetId(), + 'class'=>'layout stretch', + ]) ?> + makeLayout('form-with-sidebar') ?> + + + +
    + +
    +
    +

    fatalError)) ?>

    +

    +
    + diff --git a/modules/backend/console/scaffold/controller/sidebar/preview.stub b/modules/backend/console/scaffold/controller/sidebar/preview.stub new file mode 100644 index 0000000..dcfe79f --- /dev/null +++ b/modules/backend/console/scaffold/controller/sidebar/preview.stub @@ -0,0 +1,39 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> + + +
    + +
    + formRenderOutsideFields() ?> + formRenderPrimaryTabs() ?> +
    + +
    + + + +
    formRenderSecondaryTabs() ?>
    + + + + $this->formGetId(), + 'class'=>'layout stretch', + ]) ?> + makeLayout('form-with-sidebar') ?> + + + + +
    + +
    +
    +

    fatalError)) ?>

    +

    +
    + diff --git a/modules/backend/console/scaffold/controller/sidebar/update.stub b/modules/backend/console/scaffold/controller/sidebar/update.stub new file mode 100644 index 0000000..b7fd53c --- /dev/null +++ b/modules/backend/console/scaffold/controller/sidebar/update.stub @@ -0,0 +1,38 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> + +
    +
    + formRenderOutsideFields() ?> + formRenderPrimaryTabs() ?> +
    +
    + formMakePartial('toolbar') ?> +
    +
    + + + +
    formRenderSecondaryTabs() ?>
    + + + + $this->formGetId(), + 'class'=>'layout stretch', + ]) ?> + makeLayout('form-with-sidebar') ?> + + + +
    + +
    +
    +

    fatalError)) ?>

    +

    +
    + diff --git a/modules/backend/console/scaffold/controller/standard/create.stub b/modules/backend/console/scaffold/controller/standard/create.stub new file mode 100644 index 0000000..74d7075 --- /dev/null +++ b/modules/backend/console/scaffold/controller/standard/create.stub @@ -0,0 +1,21 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> + $this->formGetId(), + 'class' => 'layout'], + ) ?> +
    + formRender() ?> +
    + +
    + formMakePartial('toolbar') ?> +
    + + +

    fatalError) ?>

    +

    + diff --git a/modules/backend/console/scaffold/controller/standard/preview.stub b/modules/backend/console/scaffold/controller/standard/preview.stub new file mode 100644 index 0000000..d50dd41 --- /dev/null +++ b/modules/backend/console/scaffold/controller/standard/preview.stub @@ -0,0 +1,16 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> + +
    + formRenderPreview() ?> +
    + + + +

    fatalError) ?>

    +

    + + diff --git a/modules/backend/console/scaffold/controller/standard/update.stub b/modules/backend/console/scaffold/controller/standard/update.stub new file mode 100644 index 0000000..98ac41e --- /dev/null +++ b/modules/backend/console/scaffold/controller/standard/update.stub @@ -0,0 +1,20 @@ + + makeLayoutPartial('breadcrumb') ?> + + +fatalError): ?> + $this->formGetId(), + 'class' => 'layout', + ]) ?> +
    + formRender() ?> +
    +
    + formMakePartial('toolbar') ?> +
    + + +

    fatalError) ?>

    +

    + diff --git a/modules/backend/console/scaffold/formwidget/formwidget.stub b/modules/backend/console/scaffold/formwidget/formwidget.stub new file mode 100644 index 0000000..091fb61 --- /dev/null +++ b/modules/backend/console/scaffold/formwidget/formwidget.stub @@ -0,0 +1,59 @@ +prepareVars(); + return $this->makePartial('{{lower_name}}'); + } + + /** + * Prepares the form widget view data + */ + public function prepareVars() + { + $this->vars['name'] = $this->formField->getName(); + $this->vars['value'] = $this->getLoadValue(); + $this->vars['model'] = $this->model; + } + + /** + * @inheritDoc + */ + public function loadAssets() + { + $this->addCss('css/{{lower_name}}.css', '{{author}}.{{plugin}}'); + $this->addJs('js/{{lower_name}}.js', '{{author}}.{{plugin}}'); + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + return $value; + } +} diff --git a/modules/backend/console/scaffold/formwidget/javascript.stub b/modules/backend/console/scaffold/formwidget/javascript.stub new file mode 100644 index 0000000..d4765f0 --- /dev/null +++ b/modules/backend/console/scaffold/formwidget/javascript.stub @@ -0,0 +1,5 @@ +/* + * This is a sample JavaScript file used by {{name}} + * + * You can delete this file if you want + */ diff --git a/modules/backend/console/scaffold/formwidget/partial.stub b/modules/backend/console/scaffold/formwidget/partial.stub new file mode 100644 index 0000000..f311f17 --- /dev/null +++ b/modules/backend/console/scaffold/formwidget/partial.stub @@ -0,0 +1,17 @@ +previewMode): ?> + +
    + +
    + + + + + + diff --git a/modules/backend/console/scaffold/formwidget/stylesheet.stub b/modules/backend/console/scaffold/formwidget/stylesheet.stub new file mode 100644 index 0000000..203c17a --- /dev/null +++ b/modules/backend/console/scaffold/formwidget/stylesheet.stub @@ -0,0 +1,5 @@ +/* + * This is a sample StyleSheet file used by {{name}} + * + * You can delete this file if you want + */ diff --git a/modules/backend/console/scaffold/reportwidget/reportwidget.stub b/modules/backend/console/scaffold/reportwidget/reportwidget.stub new file mode 100644 index 0000000..f58a265 --- /dev/null +++ b/modules/backend/console/scaffold/reportwidget/reportwidget.stub @@ -0,0 +1,65 @@ + [ + 'title' => 'backend::lang.dashboard.widget_title_label', + 'default' => '{{title_name}} Report Widget', + 'type' => 'string', + 'validationPattern' => '^.+$', + 'validationMessage' => 'backend::lang.dashboard.widget_title_error', + ], + ]; + } + + /** + * Adds widget specific asset files. Use $this->addJs() and $this->addCss() + * to register new assets to include on the page. + * @return void + */ + protected function loadAssets() + { + } + + /** + * Renders the widget's primary contents. + * @return string HTML markup supplied by this widget. + */ + public function render() + { + try { + $this->prepareVars(); + } catch (Exception $ex) { + $this->vars['error'] = $ex->getMessage(); + } + + return $this->makePartial('{{lower_name}}'); + } + + /** + * Prepares the report widget view data + */ + public function prepareVars() + { + } +} diff --git a/modules/backend/console/scaffold/reportwidget/widget.stub b/modules/backend/console/scaffold/reportwidget/widget.stub new file mode 100644 index 0000000..13f9152 --- /dev/null +++ b/modules/backend/console/scaffold/reportwidget/widget.stub @@ -0,0 +1,9 @@ +
    +

    property('title')) ?>

    + + +

    This is the default partial content.

    + +

    + +
    diff --git a/modules/backend/controllers/AccessLogs.php b/modules/backend/controllers/AccessLogs.php new file mode 100644 index 0000000..05391cb --- /dev/null +++ b/modules/backend/controllers/AccessLogs.php @@ -0,0 +1,43 @@ +listRefresh(); + } +} diff --git a/modules/backend/controllers/Auth.php b/modules/backend/controllers/Auth.php new file mode 100644 index 0000000..549d96f --- /dev/null +++ b/modules/backend/controllers/Auth.php @@ -0,0 +1,241 @@ +layout = 'auth'; + } + + /** + * Default route, redirects to signin. + */ + public function index() + { + return Backend::redirect('backend/auth/signin'); + } + + /** + * Displays the log in page. + */ + public function signin() + { + if (BackendAuth::user()) { + return Backend::redirect('backend'); + } + + $this->bodyClass = 'signin'; + + // Clear Cache and any previous data to fix invalid security token issue + $this->setResponseHeader('Cache-Control', 'no-cache, no-store, must-revalidate'); + + try { + if (post('postback')) { + return $this->signin_onSubmit(); + } + + $this->bodyClass .= ' preload'; + } catch (Exception $ex) { + Flash::error($ex->getMessage()); + } + } + + public function signin_onSubmit() + { + $rules = [ + 'login' => 'required|between:2,255', + 'password' => 'required|between:4,255' + ]; + + $validation = Validator::make(post(), $rules); + if ($validation->fails()) { + throw new ValidationException($validation); + } + + if (is_null($remember = Config::get('cms.backendForceRemember', true))) { + $remember = (bool) post('remember'); + } + + // Authenticate user + $user = BackendAuth::authenticate([ + 'login' => post('login'), + 'password' => post('password') + ], $remember); + + // Redirect to the intended page after successful sign in + return Backend::redirectIntended('backend'); + } + + /** + * Logs out a backend user. + */ + public function signout() + { + if (BackendAuth::isImpersonator()) { + BackendAuth::stopImpersonate(); + } else { + BackendAuth::logout(); + } + + // Add HTTP Header 'Clear Site Data' to purge all sensitive data upon signout + if (Request::secure()) { + $this->setResponseHeader('Clear-Site-Data', 'cache, cookies, storage, executionContexts'); + } + + return Backend::redirect('backend'); + } + + /** + * Request a password reset verification code. + */ + public function restore() + { + $this->bodyClass = 'restore'; + + try { + if (post('postback')) { + return $this->restore_onSubmit(); + } + } catch (Exception $ex) { + Flash::error($ex->getMessage()); + } + } + + /** + * Submits the restore form. + */ + public function restore_onSubmit() + { + // Force Trusted Host verification on password reset link generation + // regardless of config to protect against host header poisoning + $trustedHosts = Config::get('app.trustedHosts', false); + if ($trustedHosts === false) { + $hosts = CheckForTrustedHost::processTrustedHosts(true); + + if (count($hosts)) { + Request::setTrustedHosts($hosts); + + // Trigger the host validation logic + Request::getHost(); + } + } + + $rules = [ + 'login' => 'required|between:2,255' + ]; + + $validation = Validator::make(post(), $rules); + if ($validation->fails()) { + throw new ValidationException($validation); + } + + $user = BackendAuth::findUserByLogin(post('login')); + + if ($user) { + $code = $user->getResetPasswordCode(); + $link = Backend::url('backend/auth/reset/' . $user->id . '/' . $code); + + $data = [ + 'name' => $user->full_name, + 'link' => $link, + ]; + + Mail::send('backend::mail.restore', $data, function ($message) use ($user) { + $message->to($user->email, $user->full_name)->subject(trans('backend::lang.account.password_reset')); + }); + } + + Flash::success(trans('backend::lang.account.restore_success')); + + return Backend::redirect('backend/auth/signin'); + } + + /** + * Reset backend user password using verification code. + */ + public function reset($userId = null, $code = null) + { + $this->bodyClass = 'reset'; + + try { + if (post('postback')) { + return $this->reset_onSubmit(); + } + + if (!$userId || !$code) { + throw new ApplicationException(trans('backend::lang.account.reset_error')); + } + } catch (Exception $ex) { + Flash::error($ex->getMessage()); + } + + $this->vars['code'] = $code; + $this->vars['id'] = $userId; + } + + /** + * Submits the reset form. + */ + public function reset_onSubmit() + { + if (!post('id') || !post('code')) { + throw new ApplicationException(trans('backend::lang.account.reset_error')); + } + + $rules = [ + 'password' => 'required|between:4,255' + ]; + + $validation = Validator::make(post(), $rules); + if ($validation->fails()) { + throw new ValidationException($validation); + } + + $code = post('code'); + $user = BackendAuth::findUserById(post('id')); + + if (!$user || !$user->checkResetPasswordCode($code)) { + throw new ApplicationException(trans('backend::lang.account.reset_error')); + } + + if (!$user->attemptResetPassword($code, post('password'))) { + throw new ApplicationException(trans('backend::lang.account.reset_fail')); + } + + $user->clearResetPassword(); + + Flash::success(trans('backend::lang.account.reset_success')); + + return Backend::redirect('backend/auth/signin'); + } +} diff --git a/modules/backend/controllers/Files.php b/modules/backend/controllers/Files.php new file mode 100644 index 0000000..37ad192 --- /dev/null +++ b/modules/backend/controllers/Files.php @@ -0,0 +1,196 @@ +findFileObject($code)->output('inline', true); + } + catch (Exception $ex) { + } + + return Response::make(View::make('backend::404'), 404); + } + + /** + * Output thumbnail, or fall back on the 404 page + */ + public function thumb($code = null, $width = 100, $height = 100, $mode = 'auto', $extension = 'auto') + { + try { + return $this->findFileObject($code)->outputThumb( + $width, + $height, + compact('mode', 'extension'), + true + ); + } + catch (Exception $ex) { + } + + return Response::make(View::make('backend::404'), 404); + } + + /** + * Attempt to return a redirect to a temporary URL to the asset instead of streaming the asset - if supported + * + * @param System|Models\File $file + * @param string|null $path Optional, defaults to the getDiskPath() of the file + * @return string|null + */ + protected static function getTemporaryUrl($file, $path = null) + { + // Get the disk used + $disk = $file->getDisk(); + + if (empty($path)) { + $path = $file->getDiskPath(); + } + + // Check to see if the URL has already been generated + $pathKey = 'backend.file:' . $path; + $url = Cache::get($pathKey, null); + + if (is_null($url) && $disk->exists($path)) { + $expires = now()->addSeconds(Config::get('cms.storage.uploads.temporaryUrlTTL', 3600)); + $url = Cache::remember($pathKey, $expires, function () use ($disk, $path, $expires) { + // Attempt to generate a temporary URL, if a RuntimeException occurs it's "probably" + // because the driver doesn't support that method + try { + return $disk->temporaryUrl($path, $expires); + } catch (RuntimeException $ex) { + return false; + } + }); + } + + // Limit the return types to strings or null + if (!is_string($url) || empty($url)) { + $url = null; + } + + return $url; + } + + /** + * Returns the URL for downloading a system file. + * @param $file System\Models\File + * @return string + */ + public static function getDownloadUrl($file) + { + $url = static::getTemporaryUrl($file); + + if (!empty($url)) { + return $url; + } else { + return Backend::url('backend/files/get/' . self::getUniqueCode($file)); + } + } + + /** + * Returns the URL for downloading a system file. + * @param $file System\Models\File + * @param $width int + * @param $height int + * @param $options array + * @return string + */ + public static function getThumbUrl($file, $width, $height, $options) + { + $url = static::getTemporaryUrl($file, $file->getDiskPath($file->getThumbFilename($width, $height, $options))); + + if (!empty($url)) { + return $url; + } else { + return Backend::url('backend/files/thumb/' . self::getUniqueCode($file)) . '/' . $width . '/' . $height . '/' . $options['mode'] . '/' . $options['extension']; + } + } + + /** + * Returns a unique code used for masking the file identifier. + * @param $file System\Models\File + * @return string + */ + public static function getUniqueCode($file) + { + if (!$file) { + return null; + } + + $hash = md5($file->file_name . '!' . $file->disk_name); + return base64_encode($file->id . '!' . $hash); + } + + /** + * Locates a file model based on the unique code. + * @param $code string + * @return System\Models\File + */ + protected function findFileObject($code) + { + if (!$code) { + throw new ApplicationException('Missing code'); + } + + $parts = explode('!', base64_decode($code)); + if (count($parts) < 2) { + throw new ApplicationException('Invalid code'); + } + + list($id, $hash) = $parts; + + if (!$file = FileModel::find((int) $id)) { + throw new ApplicationException('Unable to find file'); + } + + /** + * Ensure that the file model utilized for this request is + * the one specified in the relationship configuration + */ + if ($file->attachment) { + $fileModel = $file->attachment->{$file->field}()->getRelated(); + + /** + * Only attempt to get file model through its assigned class + * when the assigned class differs from the default one that + * the file has already been loaded from + */ + if (get_class($file) !== get_class($fileModel)) { + $file = $fileModel->find($file->id); + } + } + + $verifyCode = self::getUniqueCode($file); + if ($code != $verifyCode) { + throw new ApplicationException('Invalid hash'); + } + + return $file; + } +} diff --git a/modules/backend/controllers/Index.php b/modules/backend/controllers/Index.php new file mode 100644 index 0000000..6856a9b --- /dev/null +++ b/modules/backend/controllers/Index.php @@ -0,0 +1,81 @@ +addCss('/modules/backend/assets/css/dashboard/dashboard.css', 'core'); + } + + public function index() + { + if ($redirect = $this->checkPermissionRedirect()) { + return $redirect; + } + + $this->initReportContainer(); + + $this->pageTitle = 'backend::lang.dashboard.menu_label'; + + BackendMenu::setContextMainMenu('dashboard'); + } + + public function index_onInitReportContainer() + { + $this->initReportContainer(); + + return ['#dashReportContainer' => $this->widget->reportContainer->render()]; + } + + /** + * Prepare the report widget used by the dashboard + * @param Model $model + * @return void + */ + protected function initReportContainer() + { + new ReportContainer($this, 'config_dashboard.yaml'); + } + + /** + * Custom permissions check that will redirect to the next + * available menu item, if permission to this page is denied. + */ + protected function checkPermissionRedirect() + { + if (!$this->user->hasAccess('backend.access_dashboard')) { + if ($first = array_first(BackendMenu::listMainMenuItems())) { + return Redirect::intended($first->url); + } + return Backend::redirect('backend/myaccount'); + } + } +} diff --git a/modules/backend/controllers/Media.php b/modules/backend/controllers/Media.php new file mode 100644 index 0000000..7a3a743 --- /dev/null +++ b/modules/backend/controllers/Media.php @@ -0,0 +1,38 @@ +pageTitle = 'backend::lang.media.menu_label'; + + $manager = new MediaManager($this, 'manager'); + $manager->bindToController(); + } + + public function index() + { + $this->bodyClass = 'compact-container'; + } +} diff --git a/modules/backend/controllers/MyAccount.php b/modules/backend/controllers/MyAccount.php new file mode 100644 index 0000000..55e2723 --- /dev/null +++ b/modules/backend/controllers/MyAccount.php @@ -0,0 +1,92 @@ +whereKey($this->user->getKey()); + } + + /** + * My Account page + */ + public function index() + { + $this->pageTitle = 'backend::lang.myaccount.menu_label'; + return $this->asExtension('FormController')->update($this->user->id, 'myaccount'); + } + + /** + * Save handler for the My Account form + */ + public function index_onSave() + { + $result = $this->asExtension('FormController')->update_onSave($this->user->id, 'myaccount'); + + /* + * If the password or login name has been updated, reauthenticate the user + */ + $loginChanged = $this->user->login != post('User[login]'); + $passwordChanged = strlen(post('User[password]')); + if ($loginChanged || $passwordChanged) { + BackendAuth::login($this->user->reload(), true); + } + + return $result; + } +} diff --git a/modules/backend/controllers/Preferences.php b/modules/backend/controllers/Preferences.php new file mode 100644 index 0000000..8bfcd53 --- /dev/null +++ b/modules/backend/controllers/Preferences.php @@ -0,0 +1,79 @@ +addJs('/modules/backend/assets/js/preferences/preferences.js', 'core'); + + BackendMenu::setContext('Winter.System', 'system', 'mysettings'); + SettingsManager::setContext('Winter.Backend', 'preferences'); + } + + public function index() + { + $this->pageTitle = 'backend::lang.backend_preferences.menu_label'; + $this->asExtension('FormController')->update(); + } + + /** + * Remove the code editor tab if there is no permission. + */ + public function formExtendFields($form) + { + if (!$this->user->hasAccess('backend.manage_own_editor')) { + $form->removeTab('backend::lang.backend_preferences.code_editor'); + } + } + + public function index_onSave() + { + return $this->asExtension('FormController')->update_onSave(); + } + + public function index_onResetDefault() + { + $model = $this->formFindModelObject(); + $model->resetDefault(); + + Flash::success(Lang::get('backend::lang.form.reset_success')); + + return Backend::redirect('backend/preferences'); + } + + public function formFindModelObject() + { + return PreferenceModel::instance(); + } +} diff --git a/modules/backend/controllers/UserGroups.php b/modules/backend/controllers/UserGroups.php new file mode 100644 index 0000000..10bc257 --- /dev/null +++ b/modules/backend/controllers/UserGroups.php @@ -0,0 +1,39 @@ +bindEvent('page.beforeDisplay', function () { + if (!$this->user->isSuperUser()) { + abort(403); + } + }); + } +} diff --git a/modules/backend/controllers/Users.php b/modules/backend/controllers/Users.php new file mode 100644 index 0000000..ef0813f --- /dev/null +++ b/modules/backend/controllers/Users.php @@ -0,0 +1,258 @@ +user->isSuperUser()) { + $query->where('is_superuser', false); + } + } + + /** + * Prevents non-superusers from even seeing the is_superuser filter + */ + public function listFilterExtendScopes($filterWidget) + { + if (!$this->user->isSuperUser()) { + $filterWidget->removeScope('is_superuser'); + } + } + + /** + * Strike out deleted records + */ + public function listInjectRowClass($record, $definition = null) + { + if ($record->trashed()) { + return 'strike'; + } + } + + /** + * Extends the form query to prevent non-superusers from accessing superusers at all + */ + public function formExtendQuery($query) + { + if (!$this->user->isSuperUser()) { + $query->where('is_superuser', false); + } + + // Ensure soft-deleted records can still be managed + $query->withTrashed(); + } + + /** + * Before creating a new user, generate password if auto-generate is enabled + */ + public function formBeforeCreate($model) + { + if (post('User._auto_generate_password')) { + $password = Str::random(22); + $model->password = $password; + $model->password_confirmation = $password; + } + } + + /** + * Update controller + */ + public function update($recordId, $context = null) + { + // Users cannot edit themselves, only use My Account + if ($context != 'myaccount' && $recordId == $this->user->id) { + return Backend::redirect('backend/myaccount'); + } + + return $this->asExtension('FormController')->update($recordId, $context); + } + + /** + * Handle restoring users + */ + public function update_onRestore($recordId) + { + $this->formFindModelObject($recordId)->restore(); + + Flash::success(Lang::get('backend::lang.form.restore_success', ['name' => Lang::get('backend::lang.user.name')])); + + return Redirect::refresh(); + } + + /** + * Impersonate this user + */ + public function update_onImpersonateUser($recordId) + { + if (!$this->user->hasAccess('backend.impersonate_users')) { + return Response::make(Lang::get('backend::lang.page.access_denied.label'), 403); + } + + $model = $this->formFindModelObject($recordId); + + BackendAuth::impersonate($model); + + Flash::success(Lang::get('backend::lang.account.impersonate_success')); + + return Backend::redirect('backend/myaccount'); + } + + /** + * Unsuspend this user + */ + public function update_onUnsuspendUser($recordId) + { + $model = $this->formFindModelObject($recordId); + + $model->unsuspend(); + + Flash::success(Lang::get('backend::lang.account.unsuspend_success')); + + return Redirect::refresh(); + } + + /** + * Backward compatibility redirect to the new MyAccount controller. + */ + public function myaccount() + { + return Backend::redirect('backend/myaccount'); + } + + /** + * Add available permission fields to the User form. + * Mark default groups as checked for new Users. + */ + public function formExtendFields($form) + { + if ($form->getContext() == 'myaccount') { + return; + } + + if (!$this->user->isSuperUser()) { + $form->removeField('is_superuser'); + } + + /* + * Add permissions tab + */ + $form->addTabFields($this->generatePermissionsField()); + + /* + * Mark default groups + */ + if (!$form->model->exists) { + $defaultGroupIds = UserGroup::where('is_new_user_default', true)->lists('id'); + + $groupField = $form->getField('groups'); + if ($groupField) { + $groupField->value = $defaultGroupIds; + } + } + } + + /** + * Adds the permissions editor widget to the form. + * @return array + */ + protected function generatePermissionsField() + { + return [ + 'permissions' => [ + 'tab' => 'backend::lang.user.permissions', + 'type' => 'Backend\FormWidgets\PermissionEditor', + 'trigger' => [ + 'action' => 'disable', + 'field' => 'is_superuser', + 'condition' => 'checked' + ] + ] + ]; + } + + /** + * Send password reset mail + */ + public function update_onManualPasswordReset($recordId) + { + $user = $this->formFindModelObject($recordId); + + if ($user) { + $code = $user->getResetPasswordCode(); + $link = Backend::url('backend/auth/reset/' . $user->id . '/' . $code); + + $data = [ + 'name' => $user->full_name, + 'link' => $link, + ]; + + Mail::send('backend::mail.restore', $data, function ($message) use ($user) { + $message->to($user->email, $user->full_name)->subject(trans('backend::lang.account.password_reset')); + }); + } + + Flash::success(Lang::get('backend::lang.account.manual_password_reset_success')); + + return Redirect::refresh(); + } +} diff --git a/modules/backend/controllers/accesslogs/_hint.php b/modules/backend/controllers/accesslogs/_hint.php new file mode 100644 index 0000000..66c293f --- /dev/null +++ b/modules/backend/controllers/accesslogs/_hint.php @@ -0,0 +1,4 @@ + +

    + 60])) ?> +

    \ No newline at end of file diff --git a/modules/backend/controllers/accesslogs/_list_toolbar.php b/modules/backend/controllers/accesslogs/_list_toolbar.php new file mode 100644 index 0000000..81bfa64 --- /dev/null +++ b/modules/backend/controllers/accesslogs/_list_toolbar.php @@ -0,0 +1,9 @@ + diff --git a/modules/backend/controllers/accesslogs/config_filter.yaml b/modules/backend/controllers/accesslogs/config_filter.yaml new file mode 100644 index 0000000..2e35941 --- /dev/null +++ b/modules/backend/controllers/accesslogs/config_filter.yaml @@ -0,0 +1,16 @@ +# =================================== +# Filter Scope Definitions +# =================================== + +scopes: + + created_at: + label: backend::lang.access_log.created_at + type: daterange + conditions: created_at >= ':after' AND created_at <= ':before' + + user: + label: backend::lang.access_log.login + modelClass: Backend\Models\User + conditions: user_id in (:filtered) + nameFrom: login diff --git a/modules/backend/controllers/accesslogs/config_list.yaml b/modules/backend/controllers/accesslogs/config_list.yaml new file mode 100644 index 0000000..c146ba8 --- /dev/null +++ b/modules/backend/controllers/accesslogs/config_list.yaml @@ -0,0 +1,17 @@ +# =================================== +# List Behavior Config +# =================================== + +title: backend::lang.access_log.menu_label +list: ~/modules/backend/models/accesslog/columns.yaml +modelClass: Backend\Models\AccessLog +noRecordsMessage: backend::lang.list.no_records +recordsPerPage: 30 +showSetup: true + +toolbar: + buttons: list_toolbar + search: + prompt: backend::lang.list.search_prompt + +filter: config_filter.yaml diff --git a/modules/backend/controllers/accesslogs/index.php b/modules/backend/controllers/accesslogs/index.php new file mode 100644 index 0000000..7dab755 --- /dev/null +++ b/modules/backend/controllers/accesslogs/index.php @@ -0,0 +1,5 @@ +
    + makeHintPartial('backend_accesslogs_hint', 'hint') ?> +
    + +listRender() ?> \ No newline at end of file diff --git a/modules/backend/controllers/auth/reset.php b/modules/backend/controllers/auth/reset.php new file mode 100644 index 0000000..279a899 --- /dev/null +++ b/modules/backend/controllers/auth/reset.php @@ -0,0 +1,33 @@ +

    + + + + + + +
    +
    + + + + + + +
    + +

    + + + +

    +
    + diff --git a/modules/backend/controllers/auth/restore.php b/modules/backend/controllers/auth/restore.php new file mode 100644 index 0000000..59d2bc7 --- /dev/null +++ b/modules/backend/controllers/auth/restore.php @@ -0,0 +1,31 @@ +

    + + + + +
    +
    + + + + +
    + +

    + + + +

    +
    + + +fireViewEvent('backend.auth.extendRestoreView') ?> diff --git a/modules/backend/controllers/auth/signin.php b/modules/backend/controllers/auth/signin.php new file mode 100644 index 0000000..c8512a2 --- /dev/null +++ b/modules/backend/controllers/auth/signin.php @@ -0,0 +1,60 @@ +

    + + + + +
    +
    + + + + + + + + + +
    + + + +
    +
    + + +
    +
    + + +

    + + + + +

    + +
    + + +fireViewEvent('backend.auth.extendSigninView') ?> diff --git a/modules/backend/controllers/index/config_dashboard.yaml b/modules/backend/controllers/index/config_dashboard.yaml new file mode 100644 index 0000000..de3a20e --- /dev/null +++ b/modules/backend/controllers/index/config_dashboard.yaml @@ -0,0 +1,23 @@ +# =================================== +# Dashboard Config +# =================================== + +defaultWidgets: + + welcome: + class: Backend\ReportWidgets\Welcome + sortOrder: 50 + configuration: + ocWidgetWidth: 7 + + systemStatus: + class: System\ReportWidgets\Status + sortOrder: 60 + configuration: + ocWidgetWidth: 7 + + activeTheme: + class: Cms\ReportWidgets\ActiveTheme + sortOrder: 70 + configuration: + ocWidgetWidth: 5 diff --git a/modules/backend/controllers/index/index.php b/modules/backend/controllers/index/index.php new file mode 100644 index 0000000..971d2d6 --- /dev/null +++ b/modules/backend/controllers/index/index.php @@ -0,0 +1,23 @@ +'layout-relative dashboard-container']) ?> +
    + +
    +
    + +
    +
    +
    +
    + + + + + diff --git a/modules/backend/controllers/media/index.php b/modules/backend/controllers/media/index.php new file mode 100644 index 0000000..7ff071e --- /dev/null +++ b/modules/backend/controllers/media/index.php @@ -0,0 +1,5 @@ + + 'layout', 'onsubmit'=>'return false']) ?> + widget->manager->render() ?> + + diff --git a/modules/backend/controllers/myaccount/config_form.yaml b/modules/backend/controllers/myaccount/config_form.yaml new file mode 100644 index 0000000..060251d --- /dev/null +++ b/modules/backend/controllers/myaccount/config_form.yaml @@ -0,0 +1,12 @@ +# =================================== +# Form Behavior Config +# =================================== + +name: backend::lang.user.name +form: ~/modules/backend/models/user/fields.yaml +modelClass: Backend\Models\User +defaultRedirect: backend/myaccount + +update: + redirect: backend/myaccount + redirectClose: backend/myaccount diff --git a/modules/backend/controllers/myaccount/index.php b/modules/backend/controllers/myaccount/index.php new file mode 100644 index 0000000..a9e49f5 --- /dev/null +++ b/modules/backend/controllers/myaccount/index.php @@ -0,0 +1,56 @@ +user->hasAccess('backend.manage_users')): ?> + +
      +
    • +
    • pageTitle)) ?>
    • +
    + + + +fatalError): ?> + + +
    + +
    + formRenderOutsideFields() ?> + formRenderPrimaryTabs() ?> +
    + +
    +
    + +
    +
    + +
    + + + +
    formRenderSecondaryTabs() ?>
    + + + + 'layout stretch']) ?> + makeLayout('form-with-sidebar') ?> + + + + +
    + +
    +
    +

    fatalError)) ?>

    +

    +
    + diff --git a/modules/backend/controllers/preferences/_example_code.php b/modules/backend/controllers/preferences/_example_code.php new file mode 100644 index 0000000..7369211 --- /dev/null +++ b/modules/backend/controllers/preferences/_example_code.php @@ -0,0 +1,24 @@ +form, fieldset, h5, h6, pre, blockquote, ol, dl, dt, dd, address, dd, dtm, div, td, th, hr { + margin: 0; + padding: 0; +} + +/* This is a comment */ +body { + background-color: white; + font: 62.5% Helvetica, Arial, Tahoma, Verdana, Helvetica, sans-serif; +} + +p { + font-size: 12px; +} + +strong { + font-weight: bold; +} + +span.alert { + color: #ff0000; + border: 1px solid #ff0000; + padding: 2rem; +} diff --git a/modules/backend/controllers/preferences/_field_editor_preview_lang.php b/modules/backend/controllers/preferences/_field_editor_preview_lang.php new file mode 100644 index 0000000..33c709e --- /dev/null +++ b/modules/backend/controllers/preferences/_field_editor_preview_lang.php @@ -0,0 +1,122 @@ +

    + : + CSS | + HTML | + JavaScript | + Twig | + PHP +

    + + + + + + + + + + diff --git a/modules/backend/controllers/preferences/config_form.yaml b/modules/backend/controllers/preferences/config_form.yaml new file mode 100644 index 0000000..c9647ef --- /dev/null +++ b/modules/backend/controllers/preferences/config_form.yaml @@ -0,0 +1,8 @@ +# =================================== +# Form Behavior Config +# =================================== + +name: backend::lang.backend_preferences.menu_label +form: ~/modules/backend/models/preference/fields.yaml +modelClass: Backend\Models\Preference +defaultRedirect: system/settings diff --git a/modules/backend/controllers/preferences/index.php b/modules/backend/controllers/preferences/index.php new file mode 100644 index 0000000..1266aba --- /dev/null +++ b/modules/backend/controllers/preferences/index.php @@ -0,0 +1,41 @@ +fatalError): ?> + + 'layout']) ?> + +
    + formRender() ?> +
    + +
    +
    + + + + + + + +
    +
    + + + +

    fatalError)) ?>

    +

    + \ No newline at end of file diff --git a/modules/backend/controllers/usergroups/_list_toolbar.php b/modules/backend/controllers/usergroups/_list_toolbar.php new file mode 100644 index 0000000..bccd962 --- /dev/null +++ b/modules/backend/controllers/usergroups/_list_toolbar.php @@ -0,0 +1,8 @@ + diff --git a/modules/backend/controllers/usergroups/config_form.yaml b/modules/backend/controllers/usergroups/config_form.yaml new file mode 100644 index 0000000..9d20458 --- /dev/null +++ b/modules/backend/controllers/usergroups/config_form.yaml @@ -0,0 +1,16 @@ +# =================================== +# Form Behavior Config +# =================================== + +name: backend::lang.user.group.name +form: ~/modules/backend/models/usergroup/fields.yaml +modelClass: Backend\Models\UserGroup +defaultRedirect: backend/usergroups + +create: + redirect: backend/usergroups/update/:id + redirectClose: backend/usergroups + +update: + redirect: backend/usergroups + redirectClose: backend/usergroups diff --git a/modules/backend/controllers/usergroups/config_list.yaml b/modules/backend/controllers/usergroups/config_list.yaml new file mode 100644 index 0000000..e88b417 --- /dev/null +++ b/modules/backend/controllers/usergroups/config_list.yaml @@ -0,0 +1,16 @@ +# =================================== +# List Behavior Config +# =================================== + +title: backend::lang.user.group.list_title +list: ~/modules/backend/models/usergroup/columns.yaml +modelClass: Backend\Models\UserGroup +recordUrl: backend/usergroups/update/:id +noRecordsMessage: backend::lang.list.no_records +recordsPerPage: 25 +showSetup: true + +toolbar: + buttons: list_toolbar + search: + prompt: backend::lang.list.search_prompt diff --git a/modules/backend/controllers/usergroups/create.php b/modules/backend/controllers/usergroups/create.php new file mode 100644 index 0000000..3401241 --- /dev/null +++ b/modules/backend/controllers/usergroups/create.php @@ -0,0 +1,46 @@ + +
      +
    • +
    • +
    • pageTitle)) ?>
    • +
    + + +fatalError): ?> + + 'layout']) ?> + +
    + formRender() ?> +
    + +
    +
    + + +
    +
    + + + + +

    fatalError)) ?>

    +

    + diff --git a/modules/backend/controllers/usergroups/update.php b/modules/backend/controllers/usergroups/update.php new file mode 100644 index 0000000..fa1462d --- /dev/null +++ b/modules/backend/controllers/usergroups/update.php @@ -0,0 +1,54 @@ + +
      +
    • +
    • +
    • pageTitle)) ?>
    • +
    + + +fatalError): ?> + + 'layout']) ?> + +
    + formRender() ?> +
    + +
    +
    + + + +
    +
    + + + + +

    fatalError)) ?>

    +

    + diff --git a/modules/backend/controllers/userroles/__users.php b/modules/backend/controllers/userroles/__users.php new file mode 100644 index 0000000..f4b08fc --- /dev/null +++ b/modules/backend/controllers/userroles/__users.php @@ -0,0 +1 @@ +relationRender('users') ?> diff --git a/modules/backend/controllers/userroles/_list_toolbar.php b/modules/backend/controllers/userroles/_list_toolbar.php new file mode 100644 index 0000000..d99bf7c --- /dev/null +++ b/modules/backend/controllers/userroles/_list_toolbar.php @@ -0,0 +1,8 @@ + diff --git a/modules/backend/controllers/userroles/config_form.yaml b/modules/backend/controllers/userroles/config_form.yaml new file mode 100644 index 0000000..68b4063 --- /dev/null +++ b/modules/backend/controllers/userroles/config_form.yaml @@ -0,0 +1,16 @@ +# =================================== +# Form Behavior Config +# =================================== + +name: backend::lang.user.role.name +form: ~/modules/backend/models/userrole/fields.yaml +modelClass: Backend\Models\UserRole +defaultRedirect: backend/userroles + +create: + redirect: backend/userroles/update/:id + redirectClose: backend/userroles + +update: + redirect: backend/userroles + redirectClose: backend/userroles diff --git a/modules/backend/controllers/userroles/config_list.yaml b/modules/backend/controllers/userroles/config_list.yaml new file mode 100644 index 0000000..520fb6e --- /dev/null +++ b/modules/backend/controllers/userroles/config_list.yaml @@ -0,0 +1,16 @@ +# =================================== +# List Behavior Config +# =================================== + +title: backend::lang.user.role.list_title +list: ~/modules/backend/models/userrole/columns.yaml +modelClass: Backend\Models\UserRole +recordUrl: backend/userroles/update/:id +noRecordsMessage: backend::lang.list.no_records +recordsPerPage: 25 +showSetup: true + +toolbar: + buttons: list_toolbar + search: + prompt: backend::lang.list.search_prompt diff --git a/modules/backend/controllers/userroles/config_relation.yaml b/modules/backend/controllers/userroles/config_relation.yaml new file mode 100644 index 0000000..aa9b855 --- /dev/null +++ b/modules/backend/controllers/userroles/config_relation.yaml @@ -0,0 +1,10 @@ +# =================================== +# Relation Behavior Config +# =================================== + +users: + label: backend::lang.user.name + view: + list: ~/modules/backend/models/user/columns.yaml + toolbarButtons: add|remove + recordUrl: backend/users/update/:id diff --git a/modules/backend/controllers/userroles/create.php b/modules/backend/controllers/userroles/create.php new file mode 100644 index 0000000..0ba5e30 --- /dev/null +++ b/modules/backend/controllers/userroles/create.php @@ -0,0 +1,46 @@ + +
      +
    • +
    • +
    • pageTitle)) ?>
    • +
    + + +fatalError): ?> + + 'layout']) ?> + +
    + formRender() ?> +
    + +
    +
    + + +
    +
    + + + + +

    fatalError)) ?>

    +

    + diff --git a/modules/backend/controllers/userroles/update.php b/modules/backend/controllers/userroles/update.php new file mode 100644 index 0000000..888c15e --- /dev/null +++ b/modules/backend/controllers/userroles/update.php @@ -0,0 +1,54 @@ + +
      +
    • +
    • +
    • pageTitle)) ?>
    • +
    + + +fatalError): ?> + + 'layout']) ?> + +
    + formRender() ?> +
    + +
    +
    + + + +
    +
    + + + + +

    fatalError)) ?>

    +

    + diff --git a/modules/backend/controllers/users/_btn_impersonate.php b/modules/backend/controllers/users/_btn_impersonate.php new file mode 100644 index 0000000..4fe629a --- /dev/null +++ b/modules/backend/controllers/users/_btn_impersonate.php @@ -0,0 +1,14 @@ +user->hasAccess('backend.impersonate_users')): ?> +
    + +
    + \ No newline at end of file diff --git a/modules/backend/controllers/users/_btn_password_reset.php b/modules/backend/controllers/users/_btn_password_reset.php new file mode 100644 index 0000000..78dc211 --- /dev/null +++ b/modules/backend/controllers/users/_btn_password_reset.php @@ -0,0 +1,12 @@ +
    + +
    diff --git a/modules/backend/controllers/users/_btn_unsuspend.php b/modules/backend/controllers/users/_btn_unsuspend.php new file mode 100644 index 0000000..e917ee3 --- /dev/null +++ b/modules/backend/controllers/users/_btn_unsuspend.php @@ -0,0 +1,14 @@ +isSuspended()): ?> +
    + +
    + diff --git a/modules/backend/controllers/users/_hint_trashed.php b/modules/backend/controllers/users/_hint_trashed.php new file mode 100644 index 0000000..7c15ebd --- /dev/null +++ b/modules/backend/controllers/users/_hint_trashed.php @@ -0,0 +1,9 @@ +
    +
    +
    + +

    +

    +
    +
    +
    \ No newline at end of file diff --git a/modules/backend/controllers/users/_list_toolbar.php b/modules/backend/controllers/users/_list_toolbar.php new file mode 100644 index 0000000..f81c1c2 --- /dev/null +++ b/modules/backend/controllers/users/_list_toolbar.php @@ -0,0 +1,29 @@ +
    + + + + user->isSuperUser()): ?> + + + + + + + + + + +
    + */ ?> +
    diff --git a/modules/backend/controllers/users/config_filter.yaml b/modules/backend/controllers/users/config_filter.yaml new file mode 100644 index 0000000..d9660cc --- /dev/null +++ b/modules/backend/controllers/users/config_filter.yaml @@ -0,0 +1,30 @@ +# =================================== +# Filter Scope Definitions +# =================================== + +scopes: + + is_superuser: + label: backend::lang.user.superuser + type: switch + conditions: + - is_superuser = 0 + - is_superuser = 1 + + login_date: + label: backend::lang.user.last_login + type: daterange + conditions: last_login >= ':after' AND last_login <= ':before' + + role_id: + label: backend::lang.user.role.name + modelClass: Backend\Models\UserRole + conditions: role_id in (:filtered) + nameFrom: name + + show_deleted: + label: backend::lang.user.show_deleted + type: checkbox + modelClass: Backend\Models\User + scope: withTrashed + default: 0 diff --git a/modules/backend/controllers/users/config_form.yaml b/modules/backend/controllers/users/config_form.yaml new file mode 100644 index 0000000..cb83a00 --- /dev/null +++ b/modules/backend/controllers/users/config_form.yaml @@ -0,0 +1,16 @@ +# =================================== +# Form Behavior Config +# =================================== + +name: backend::lang.user.name +form: ~/modules/backend/models/user/fields.yaml +modelClass: Backend\Models\User +defaultRedirect: backend/users + +create: + redirect: backend/users/update/:id + redirectClose: backend/users + +update: + redirect: backend/users + redirectClose: backend/users diff --git a/modules/backend/controllers/users/config_list.yaml b/modules/backend/controllers/users/config_list.yaml new file mode 100644 index 0000000..5dcd9ee --- /dev/null +++ b/modules/backend/controllers/users/config_list.yaml @@ -0,0 +1,19 @@ +# =================================== +# List Behavior Config +# =================================== + +title: backend::lang.user.list_title +list: ~/modules/backend/models/user/columns.yaml +modelClass: Backend\Models\User +recordUrl: backend/users/update/:id +noRecordsMessage: backend::lang.list.no_records +recordsPerPage: 20 +showSetup: true +# showCheckboxes: true + +toolbar: + buttons: list_toolbar + search: + prompt: backend::lang.list.search_prompt + +filter: config_filter.yaml diff --git a/modules/backend/controllers/users/config_relation.yaml b/modules/backend/controllers/users/config_relation.yaml new file mode 100644 index 0000000..bcb19cd --- /dev/null +++ b/modules/backend/controllers/users/config_relation.yaml @@ -0,0 +1,31 @@ +# =================================== +# Relation Behavior Config +# =================================== + +throttle: + label: backend::lang.user.throttle_tab_label + view: + list: + columns: + ip_address: + label: backend::lang.user.throttle_ip_address + searchable: true + attempts: + label: backend::lang.user.throttle_attempts + width: 100px + align: center + last_attempt_at: + label: backend::lang.user.throttle_last_attempt + type: datetime + searchable: true + suspended_at: + label: backend::lang.user.throttle_suspended_at + type: datetime + searchable: true + toolbarButtons: delete|refresh + showSearch: true + showSorting: true + recordsPerPage: 10 + defaultSort: + column: last_attempt_at + direction: desc diff --git a/modules/backend/controllers/users/myaccount.php b/modules/backend/controllers/users/myaccount.php new file mode 100644 index 0000000..9c91187 --- /dev/null +++ b/modules/backend/controllers/users/myaccount.php @@ -0,0 +1,68 @@ +user->hasAccess('backend.manage_users')): ?> + +
      +
    • +
    • pageTitle)) ?>
    • +
    + + + +fatalError): ?> + + +
    + +
    + formRenderOutsideFields() ?> + formRenderPrimaryTabs() ?> +
    + +
    +
    + + user->hasAccess('backend.manage_users')): ?> + + +
    +
    + +
    + + + +
    formRenderSecondaryTabs() ?>
    + + + + 'layout stretch']) ?> + makeLayout('form-with-sidebar') ?> + + + + +
    + +
    +
    +

    fatalError)) ?>

    +

    +
    + diff --git a/modules/backend/controllers/users/update.php b/modules/backend/controllers/users/update.php new file mode 100644 index 0000000..6317998 --- /dev/null +++ b/modules/backend/controllers/users/update.php @@ -0,0 +1,88 @@ + +
      +
    • +
    • pageTitle)) ?>
    • +
    + + +fatalError): ?> + + + trashed()): ?> + makePartial('hint_trashed') ?> + + +
    + +
    + formRenderOutsideFields() ?> + formRenderPrimaryTabs() ?> +
    + +
    +
    + + + + + + trashed()): ?> + + + + +
    +
    + +
    + + + +
    formRenderSecondaryTabs() ?>
    + + + + 'layout stretch']) ?> + makeLayout('form-with-sidebar') ?> + + + + +
    + +
    +
    +

    fatalError)) ?>

    +

    +
    + diff --git a/modules/backend/database/migrations/2013_10_01_000001_Db_Backend_Users.php b/modules/backend/database/migrations/2013_10_01_000001_Db_Backend_Users.php new file mode 100644 index 0000000..1f6808a --- /dev/null +++ b/modules/backend/database/migrations/2013_10_01_000001_Db_Backend_Users.php @@ -0,0 +1,35 @@ +engine = 'InnoDB'; + $table->increments('id'); + $table->string('first_name')->nullable(); + $table->string('last_name')->nullable(); + $table->string('login')->unique('login_unique')->index('login_index'); + $table->string('email')->unique('email_unique'); + $table->string('password'); + $table->string('activation_code')->nullable()->index('act_code_index'); + $table->string('persist_code')->nullable(); + $table->string('reset_password_code')->nullable()->index('reset_code_index'); + $table->text('permissions')->nullable(); + $table->boolean('is_activated')->default(0); + $table->integer('role_id')->unsigned()->nullable()->index('admin_role_index'); + $table->timestamp('activated_at')->nullable(); + $table->timestamp('last_login')->nullable(); + $table->timestamps(); + $table->timestamp('deleted_at')->nullable(); + }); + } + + public function down() + { + Schema::dropIfExists('backend_users'); + } +} diff --git a/modules/backend/database/migrations/2013_10_01_000002_Db_Backend_User_Groups.php b/modules/backend/database/migrations/2013_10_01_000002_Db_Backend_User_Groups.php new file mode 100644 index 0000000..d465beb --- /dev/null +++ b/modules/backend/database/migrations/2013_10_01_000002_Db_Backend_User_Groups.php @@ -0,0 +1,22 @@ +engine = 'InnoDB'; + $table->increments('id'); + $table->string('name')->unique('name_unique'); + $table->timestamps(); + }); + } + + public function down() + { + Schema::dropIfExists('backend_user_groups'); + } +} diff --git a/modules/backend/database/migrations/2013_10_01_000003_Db_Backend_Users_Groups.php b/modules/backend/database/migrations/2013_10_01_000003_Db_Backend_Users_Groups.php new file mode 100644 index 0000000..c1f1728 --- /dev/null +++ b/modules/backend/database/migrations/2013_10_01_000003_Db_Backend_Users_Groups.php @@ -0,0 +1,22 @@ +engine = 'InnoDB'; + $table->integer('user_id')->unsigned(); + $table->integer('user_group_id')->unsigned(); + $table->primary(['user_id', 'user_group_id'], 'user_group'); + }); + } + + public function down() + { + Schema::dropIfExists('backend_users_groups'); + } +} diff --git a/modules/backend/database/migrations/2013_10_01_000004_Db_Backend_User_Throttle.php b/modules/backend/database/migrations/2013_10_01_000004_Db_Backend_User_Throttle.php new file mode 100644 index 0000000..df03520 --- /dev/null +++ b/modules/backend/database/migrations/2013_10_01_000004_Db_Backend_User_Throttle.php @@ -0,0 +1,28 @@ +engine = 'InnoDB'; + $table->increments('id'); + $table->integer('user_id')->unsigned()->nullable()->index(); + $table->string('ip_address')->nullable()->index(); + $table->integer('attempts')->default(0); + $table->timestamp('last_attempt_at')->nullable(); + $table->boolean('is_suspended')->default(0); + $table->timestamp('suspended_at')->nullable(); + $table->boolean('is_banned')->default(0); + $table->timestamp('banned_at')->nullable(); + }); + } + + public function down() + { + Schema::dropIfExists('backend_user_throttle'); + } +} diff --git a/modules/backend/database/migrations/2014_01_04_000005_Db_Backend_User_Preferences.php b/modules/backend/database/migrations/2014_01_04_000005_Db_Backend_User_Preferences.php new file mode 100644 index 0000000..5b98eb3 --- /dev/null +++ b/modules/backend/database/migrations/2014_01_04_000005_Db_Backend_User_Preferences.php @@ -0,0 +1,26 @@ +engine = 'InnoDB'; + $table->increments('id'); + $table->integer('user_id')->unsigned(); + $table->string('namespace', 100); + $table->string('group', 50); + $table->string('item', 150); + $table->text('value')->nullable(); + $table->index(['user_id', 'namespace', 'group', 'item'], 'user_item_index'); + }); + } + + public function down() + { + Schema::dropIfExists('backend_user_preferences'); + } +} diff --git a/modules/backend/database/migrations/2014_10_01_000006_Db_Backend_Access_Log.php b/modules/backend/database/migrations/2014_10_01_000006_Db_Backend_Access_Log.php new file mode 100644 index 0000000..fa0692f --- /dev/null +++ b/modules/backend/database/migrations/2014_10_01_000006_Db_Backend_Access_Log.php @@ -0,0 +1,23 @@ +engine = 'InnoDB'; + $table->increments('id'); + $table->integer('user_id')->unsigned(); + $table->string('ip_address')->nullable(); + $table->timestamps(); + }); + } + + public function down() + { + Schema::dropIfExists('backend_access_log'); + } +} diff --git a/modules/backend/database/migrations/2014_10_01_000007_Db_Backend_Add_Description_Field.php b/modules/backend/database/migrations/2014_10_01_000007_Db_Backend_Add_Description_Field.php new file mode 100644 index 0000000..5252fae --- /dev/null +++ b/modules/backend/database/migrations/2014_10_01_000007_Db_Backend_Add_Description_Field.php @@ -0,0 +1,25 @@ +string('code')->nullable()->index('code_index'); + $table->text('description')->nullable(); + $table->boolean('is_new_user_default')->default(false); + }); + } + + public function down() + { + // Schema::table('backend_user_groups', function (Blueprint $table) { + // $table->dropColumn('code'); + // $table->dropColumn('description'); + // $table->dropColumn('is_new_user_default'); + // }); + } +} diff --git a/modules/backend/database/migrations/2015_10_01_000008_Db_Backend_Add_Superuser_Flag.php b/modules/backend/database/migrations/2015_10_01_000008_Db_Backend_Add_Superuser_Flag.php new file mode 100644 index 0000000..e72897e --- /dev/null +++ b/modules/backend/database/migrations/2015_10_01_000008_Db_Backend_Add_Superuser_Flag.php @@ -0,0 +1,29 @@ +boolean('is_superuser')->default(false); + }); + + AdminModel::all()->each(function ($user) { + if ($user->hasPermission('superuser')) { + $user->is_superuser = true; + $user->save(); + } + }); + } + + public function down() + { + // Schema::table('backend_users', function (Blueprint $table) { + // $table->dropColumn('is_superuser'); + // }); + } +} diff --git a/modules/backend/database/migrations/2016_10_01_000009_Db_Backend_Timestamp_Fix.php b/modules/backend/database/migrations/2016_10_01_000009_Db_Backend_Timestamp_Fix.php new file mode 100644 index 0000000..553dec7 --- /dev/null +++ b/modules/backend/database/migrations/2016_10_01_000009_Db_Backend_Timestamp_Fix.php @@ -0,0 +1,39 @@ +backendTables as $table) { + DbDongle::convertTimestamps($table); + } + + // Use this opportunity to reset backend preferences for stable + Db::table('backend_user_preferences') + ->where('namespace', 'backend') + ->where('group', 'backend') + ->where('item', 'preferences') + ->delete(); + } + + public function down() + { + // ... + } +} diff --git a/modules/backend/database/migrations/2017_10_01_000010_Db_Backend_User_Roles.php b/modules/backend/database/migrations/2017_10_01_000010_Db_Backend_User_Roles.php new file mode 100644 index 0000000..fe6f15b --- /dev/null +++ b/modules/backend/database/migrations/2017_10_01_000010_Db_Backend_User_Roles.php @@ -0,0 +1,165 @@ +engine = 'InnoDB'; + $table->increments('id'); + $table->string('name')->unique('role_unique'); + $table->string('code')->nullable()->index('role_code_index'); + $table->text('description')->nullable(); + $table->text('permissions')->nullable(); + $table->boolean('is_system')->default(0); + $table->timestamps(); + }); + + // This detects older builds and performs a migration to include + // the new role system. This column will exist for new installs + // so this heavy migration process does not need to execute. + $this->migratePreviousBuild(); + } + + public function down() + { + Schema::dropIfExists('backend_user_roles'); + } + + protected function migratePreviousBuild() + { + // Role not found in the users table, perform a complete migration. + // Merging group permissions with the user and assigning the user + // with the first available role. + if (!Schema::hasColumn('backend_users', 'role_id')) { + Schema::table('backend_users', function (Blueprint $table) { + $table->integer('role_id')->unsigned()->nullable()->index('admin_role_index'); + }); + + $this->createSystemUserRoles(); + $this->migratePermissionsFromGroupsToRoles(); + } + + // Drop permissions column on groups table as it is no longer needed. + if (Schema::hasColumn('backend_user_groups', 'permissions')) { + Schema::table('backend_user_groups', function (Blueprint $table) { + $table->dropColumn('permissions'); + }); + } + } + + protected function createSystemUserRoles() + { + Db::table('backend_user_roles')->insert([ + 'name' => 'Publisher', + 'code' => UserRole::CODE_PUBLISHER, + 'description' => 'Site editor with access to publishing tools.', + ]); + + Db::table('backend_user_roles')->insert([ + 'name' => 'Developer', + 'code' => UserRole::CODE_DEVELOPER, + 'description' => 'Site administrator with access to developer tools.', + ]); + } + + protected function migratePermissionsFromGroupsToRoles() + { + $groups = Db::table('backend_user_groups')->get(); + $roles = []; + $permissions = []; + + /* + * Carbon copy groups to roles + */ + foreach ($groups as $group) { + if (!isset($group->name) || !$group->name) { + continue; + } + + try { + $roles[$group->id] = Db::table('backend_user_roles')->insertGetId([ + 'name' => $group->name, + 'description' => $group->description, + 'permissions' => $group->permissions ?? null + ]); + } + catch (Exception $ex) { + } + + $permissions[$group->id] = $group->permissions ?? null; + } + + /* + * Assign a user with the first available role + */ + $found = []; + $joins = Db::table('backend_users_groups')->get(); + + foreach ($joins as $join) { + if (!$roleId = array_get($roles, $join->user_group_id)) { + continue; + } + + $userId = $join->user_id; + + if (!isset($found[$userId])) { + Db::table('backend_users')->where('id', $userId)->update([ + 'role_id' => $roleId + ]); + } + + $found[$userId][] = $join->user_group_id; + } + + /* + * Merge group permissions in to user + */ + foreach ($found as $userId => $groups) { + $userPerms = []; + + foreach ($groups as $groupId) { + if (!$permString = array_get($permissions, $groupId)) { + continue; + } + + try { + $perms = json_decode($permString, true); + $userPerms = array_merge($userPerms, $perms); + } + catch (Exception $ex) { + } + } + + if (count($userPerms) > 0) { + $this->splicePermissionsForUser($userId, $userPerms); + } + } + } + + protected function splicePermissionsForUser($userId, $permissions) + { + /* + * Look up user and splice the provided permissions in + */ + $user = Db::table('backend_users')->where('id', $userId)->first(); + if (!$user) { + return; + } + + try { + $currentPerms = $user->permissions ? json_decode($user->permissions, true) : []; + $newPerms = array_merge($permissions, $currentPerms); + + Db::table('backend_users')->where('id', $userId)->update([ + 'permissions' => json_encode($newPerms) + ]); + } + catch (Exception $ex) { + } + } +} diff --git a/modules/backend/database/migrations/2018_12_16_000011_Db_Backend_Add_Deleted_At.php b/modules/backend/database/migrations/2018_12_16_000011_Db_Backend_Add_Deleted_At.php new file mode 100644 index 0000000..50aee8c --- /dev/null +++ b/modules/backend/database/migrations/2018_12_16_000011_Db_Backend_Add_Deleted_At.php @@ -0,0 +1,25 @@ +timestamp('deleted_at')->nullable()->after('updated_at'); + }); + } + } + + public function down() + { + if (Schema::hasColumn('backend_users', 'deleted_at')) { + Schema::table('backend_users', function (Blueprint $table) { + $table->dropColumn('deleted_at'); + }); + } + } +} diff --git a/modules/backend/database/migrations/2023_02_16_000012_Db_Backend_Add_User_Metadata.php b/modules/backend/database/migrations/2023_02_16_000012_Db_Backend_Add_User_Metadata.php new file mode 100644 index 0000000..b60735c --- /dev/null +++ b/modules/backend/database/migrations/2023_02_16_000012_Db_Backend_Add_User_Metadata.php @@ -0,0 +1,25 @@ +mediumText('metadata')->nullable()->after('permissions'); + }); + } + } + + public function down() + { + if (Schema::hasColumn('backend_users', 'metadata')) { + Schema::table('backend_users', function (Blueprint $table) { + $table->dropColumn('metadata'); + }); + } + } +} diff --git a/modules/backend/database/migrations/2023_09_09_000013_Db_Backend_Add_Users_Groups_Delete_At.php b/modules/backend/database/migrations/2023_09_09_000013_Db_Backend_Add_Users_Groups_Delete_At.php new file mode 100644 index 0000000..3db016b --- /dev/null +++ b/modules/backend/database/migrations/2023_09_09_000013_Db_Backend_Add_Users_Groups_Delete_At.php @@ -0,0 +1,25 @@ +timestamp('deleted_at')->nullable()->after('user_group_id'); + }); + } + } + + public function down() + { + if (Schema::hasColumn('backend_users_groups', 'deleted_at')) { + Schema::table('backend_users_groups', function (Blueprint $table) { + $table->dropColumn('deleted_at'); + }); + } + } +} diff --git a/modules/backend/database/seeds/DatabaseSeeder.php b/modules/backend/database/seeds/DatabaseSeeder.php new file mode 100644 index 0000000..3a8d6d7 --- /dev/null +++ b/modules/backend/database/seeds/DatabaseSeeder.php @@ -0,0 +1,33 @@ +setDefaults([ + 'password' => $adminPassword + ]); + $this->call($adminSeeder); + }); + + return ($shouldRandomizePassword) + ? 'The following password has been automatically generated for the "admin" account: ' . $adminPassword . '' + : ''; + } +} diff --git a/modules/backend/database/seeds/SeedSetupAdmin.php b/modules/backend/database/seeds/SeedSetupAdmin.php new file mode 100644 index 0000000..7796738 --- /dev/null +++ b/modules/backend/database/seeds/SeedSetupAdmin.php @@ -0,0 +1,62 @@ + $value) { + static::$$attribute = $value; + } + } + + public function run() + { + UserRole::create([ + 'name' => 'Publisher', + 'code' => UserRole::CODE_PUBLISHER, + 'description' => 'Site editor with access to publishing tools.', + ]); + + $role = UserRole::create([ + 'name' => 'Developer', + 'code' => UserRole::CODE_DEVELOPER, + 'description' => 'Site administrator with access to developer tools.', + ]); + + $group = UserGroup::create([ + 'name' => 'Owners', + 'code' => UserGroup::CODE_OWNERS, + 'description' => 'Default group for website owners.', + 'is_new_user_default' => false + ]); + + $user = User::create([ + 'email' => static::$email, + 'login' => static::$login, + 'password' => static::$password, + 'password_confirmation' => static::$password, + 'first_name' => static::$firstName, + 'last_name' => static::$lastName, + 'permissions' => [], + 'is_superuser' => true, + 'is_activated' => true, + 'role_id' => $role->id + ]); + + $user->addGroup($group); + } +} diff --git a/modules/backend/facades/Backend.php b/modules/backend/facades/Backend.php new file mode 100644 index 0000000..1d679a0 --- /dev/null +++ b/modules/backend/facades/Backend.php @@ -0,0 +1,29 @@ +applyEditorPreferences(); + + if ($this->formField->disabled) { + $this->readOnly = true; + } + + $this->fillFromConfig([ + 'language', + 'showGutter', + 'wordWrap', + 'codeFolding', + 'autoClosing', + 'useSoftTabs', + 'tabSize', + 'fontSize', + 'margin', + 'scrollPastEnd', + 'theme', + 'showInvisibles', + 'highlightActiveLine', + 'readOnly', + 'displayIndentGuides', + 'showPrintMargin', + 'showMinimap', + 'bracketColors', + 'showColors', + ]); + } + + /** + * @inheritDoc + */ + public function render() + { + $this->prepareVars(); + return $this->makePartial('codeeditor'); + } + + /** + * Prepares the widget data + */ + public function prepareVars() + { + $this->vars['fontSize'] = $this->fontSize; + $this->vars['wordWrap'] = $this->wordWrap; + $this->vars['codeFolding'] = $this->codeFolding; + $this->vars['autoClosing'] = $this->autoClosing; + $this->vars['tabSize'] = $this->tabSize; + $this->vars['theme'] = $this->theme; + $this->vars['showInvisibles'] = $this->showInvisibles; + $this->vars['highlightActiveLine'] = $this->highlightActiveLine; + $this->vars['useSoftTabs'] = $this->useSoftTabs; + $this->vars['showGutter'] = $this->showGutter; + $this->vars['language'] = $this->language; + $this->vars['margin'] = $this->margin; + $this->vars['scrollPastEnd'] = $this->scrollPastEnd; + $this->vars['stretch'] = $this->formField->stretch; + $this->vars['size'] = $this->formField->size; + $this->vars['readOnly'] = $this->readOnly; + $this->vars['displayIndentGuides'] = $this->displayIndentGuides; + $this->vars['showPrintMargin'] = $this->showPrintMargin; + $this->vars['showMinimap'] = $this->showMinimap; + $this->vars['bracketColors'] = $this->bracketColors; + $this->vars['showColors'] = $this->showColors; + + // Double encode when escaping + $this->vars['value'] = htmlentities($this->getLoadValue(), ENT_QUOTES, 'UTF-8', true); + $this->vars['name'] = $this->getFieldName(); + } + + /** + * @inheritDoc + */ + protected function loadAssets() + { + $this->addCss('css/codeeditor.css', 'core'); + $this->addJs('js/build/codeeditor.bundle.js', 'core'); + } + + /** + * Looks at the user preferences and overrides any set values. + * @return void + */ + protected function applyEditorPreferences() + { + // Load the editor system settings + $preferences = BackendPreference::instance(); + + $this->fontSize = $preferences->editor_font_size; + $this->wordWrap = $preferences->editor_word_wrap; + $this->codeFolding = $preferences->editor_enable_folding ?? ($preferences->editor_code_folding !== 'manual'); + $this->autoClosing = $preferences->editor_auto_closing; + $this->tabSize = $preferences->editor_tab_size; + $this->theme = $preferences->editor_theme; + $this->showInvisibles = $preferences->editor_show_invisibles; + $this->highlightActiveLine = $preferences->editor_highlight_active_line; + $this->useSoftTabs = !$preferences->editor_use_hard_tabs; + $this->showGutter = $preferences->editor_show_gutter; + $this->displayIndentGuides = $preferences->editor_display_indent_guides; + $this->showPrintMargin = $preferences->editor_show_print_margin; + $this->showMinimap = $preferences->editor_show_minimap; + $this->bracketColors = $preferences->editor_bracket_colors; + $this->showColors = $preferences->editor_show_colors; + } +} diff --git a/modules/backend/formwidgets/ColorPicker.php b/modules/backend/formwidgets/ColorPicker.php new file mode 100644 index 0000000..248b078 --- /dev/null +++ b/modules/backend/formwidgets/ColorPicker.php @@ -0,0 +1,286 @@ + '/^cmyk\((\d{1,2}\.?\d{0,2}%,? ?){4}\)$/', + 'hex' => '/^#[\w\d]{6,8}$/', + 'hsl' => '/^hsla\((\d{1,3}\.?\d{0,2}%?, ?){3}\d\.?\d{0,2}?\)$/', + 'rgb' => '/^rgba\((\d{1,3}\.?\d{0,2}, ?){3}\d\.?\d{0,2}?\)$/', + ]; + + // + // Object properties + // + + /** + * @inheritDoc + */ + protected $defaultAlias = 'colorpicker'; + + /** + * @inheritDoc + */ + public function init() + { + $this->fillFromConfig([ + 'availableColors', + 'formats', + 'allowEmpty', + 'allowCustom', + 'showAlpha', + 'readOnly', + 'disabled', + ]); + } + + /** + * @inheritDoc + */ + public function render() + { + $this->prepareVars(); + return $this->makePartial('colorpicker'); + } + + /** + * Prepares the list data + */ + public function prepareVars() + { + $this->vars['name'] = $this->getFieldName(); + $this->vars['value'] = $this->getLoadValue(); + $this->vars['availableColors'] = $this->getAvailableColors(); + $this->vars['formats'] = $this->getFormats(); + $this->vars['allowEmpty'] = (bool) $this->allowEmpty; + $this->vars['allowCustom'] = (bool) $this->allowCustom; + $this->vars['showAlpha'] = (bool) $this->showAlpha; + $this->vars['readOnly'] = (bool) $this->readOnly; + $this->vars['disabled'] = (bool) $this->disabled; + } + + /** + * Gets the appropriate list of colors. + * + * @return array + */ + protected function getAvailableColors() + { + $availableColors = $this->availableColors; + + if (is_array($availableColors)) { + return $availableColors; + } elseif (is_string($availableColors) && !empty($availableColors)) { + if ($this->model->methodExists($availableColors)) { + return $this->availableColors = $this->model->{$availableColors}( + $this->formField->fieldName, + $this->formField->value, + $this->formField->config + ); + } else { + throw new ApplicationException(Lang::get('backend::lang.field.colors_method_not_exists', [ + 'model' => get_class($this->model), + 'method' => $availableColors, + 'field' => $this->formField->fieldName + ])); + } + } else { + return $this->availableColors = array_map(function ($color) { + return $color['color']; + }, BrandSetting::get('default_colors', [ + [ + 'color' => '#1abc9c', + ], + [ + 'color' => '#16a085', + ], + [ + 'color' => '#6cc551', + ], + [ + 'color' => '#52a838', + ], + [ + 'color' => '#b1dbef', + ], + [ + 'color' => '#88c9e7', + ], + [ + 'color' => '#2da7c7', + ], + [ + 'color' => '#227f96', + ], + [ + 'color' => '#b281c5', + ], + [ + 'color' => '#7b4e8e', + ], + [ + 'color' => '#103141', + ], + [ + 'color' => '#081821', + ], + [ + 'color' => '#f8e095', + ], + [ + 'color' => '#dcb22d', + ], + [ + 'color' => '#de8754', + ], + [ + 'color' => '#d66829', + ], + [ + 'color' => '#b33f32', + ], + [ + 'color' => '#ab2a1c', + ], + [ + 'color' => '#95a5a6', + ], + [ + 'color' => '#7f8c8d', + ], + ])); + } + } + + /** + * Returns the allowed color formats. + * + * If no valid formats are specified, the "hex" format will be used. + * + * @return array + */ + protected function getFormats() + { + if ($this->formats === 'all') { + return static::ALL_FORMATS; + } + + $availableFormats = []; + $configFormats = (is_string($this->formats)) + ? [$this->formats] + : $this->formats; + + foreach ($configFormats as $format) { + if (in_array($format, static::ALL_FORMATS)) { + $availableFormats[] = $format; + } + } + + return (count($availableFormats)) + ? $availableFormats + : ['hex']; + } + + /** + * @inheritDoc + */ + protected function loadAssets() + { + $this->addJs('js/dist/colorpicker.js', 'core'); + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + if (!strlen($value)) { + return null; + } + + switch (is_array($this->formats) ? 'all' : $this->formats) { + case 'cmyk': + case 'hex': + case 'hsl': + case 'rgb': + if (!preg_match($this->validationPatterns[$this->formats], $value)) { + throw new ApplicationException(Lang::get('backend::lang.field.colors_invalid_input')); + } + break; + case 'all': + $valid = false; + foreach ($this->validationPatterns as $pattern) { + if (preg_match($pattern, $value)) { + $valid = true; + break; + } + } + if (!$valid) { + throw new ApplicationException(Lang::get('backend::lang.field.colors_invalid_input')); + } + break; + } + + return $value; + } +} diff --git a/modules/backend/formwidgets/DataTable.php b/modules/backend/formwidgets/DataTable.php new file mode 100644 index 0000000..3a5c26c --- /dev/null +++ b/modules/backend/formwidgets/DataTable.php @@ -0,0 +1,205 @@ +fillFromConfig([ + 'size', + 'rowSorting', + ]); + + $this->table = $this->makeTableWidget(); + $this->table->bindToController(); + } + + /** + * @return Backend\Widgets\Table The table to be displayed. + */ + public function getTable() + { + return $this->table; + } + + /** + * @inheritDoc + */ + public function render() + { + $this->prepareVars(); + return $this->makePartial('datatable'); + } + + /** + * Prepares the list data + */ + public function prepareVars() + { + $this->populateTableWidget(); + $this->vars['table'] = $this->table; + $this->vars['size'] = $this->size; + $this->vars['rowSorting'] = $this->rowSorting; + } + + /** + * @inheritDoc + */ + public function getLoadValue() + { + $value = (array) parent::getLoadValue(); + + // Sync the array keys as the ID to make the + // table widget happy! + foreach ($value as $key => $_value) { + $value[$key] = ['id' => $key] + (array) $_value; + } + + return $value; + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + // TODO: provide a streaming implementation of saving + // data to the model. The current implementation returns + // all records at once. -ab + + $dataSource = $this->table->getDataSource(); + + $result = []; + while ($records = $dataSource->readRecords()) { + $result = array_merge($result, $records); + } + + // We should be dealing with a simple array, so + // strip out the id columns in the final array. + foreach ($result as $key => $_result) { + unset($result[$key]['id']); + } + + return $result; + } + + /* + * Populate data + */ + protected function populateTableWidget() + { + $dataSource = $this->table->getDataSource(); + + // TODO: provide a streaming implementation of loading + // data from the model. The current implementation loads + // all records at once. -ab + + $records = $this->getLoadValue() ?: []; + + $dataSource->purge(); + $dataSource->initRecords((array) $records); + } + + protected function makeTableWidget() + { + $config = $this->makeConfig((array) $this->config); + + $config->dataSource = 'client'; + if (isset($this->getParentForm()->arrayName)) { + $config->alias = studly_case(HtmlHelper::nameToId($this->getParentForm()->arrayName . '[' . $this->fieldName . ']')) . 'datatable'; + $config->fieldName = $this->getParentForm()->arrayName . '[' . $this->fieldName . ']'; + } else { + $config->alias = studly_case(HtmlHelper::nameToId($this->fieldName)) . 'datatable'; + $config->fieldName = $this->fieldName; + } + + $table = new Table($this->controller, $config); + + $table->bindEvent('table.getDropdownOptions', [$this, 'getDataTableOptions']); + + return $table; + } + + /** + * Dropdown/autocomplete option callback handler + * + * Looks at the model for getXXXDataTableOptions or getDataTableOptions methods + * to obtain values for autocomplete and dropdown column types. + * + * @param string $columnName The name of the column to pass through to the callback. + * @param array $rowData The data provided for the current row in the datatable. + * @return array The options to make available to the dropdown or autocomplete, in format ["value" => "label"] + */ + public function getDataTableOptions($columnName, $rowData) + { + $methodName = 'get' . studly_case($this->fieldName) . 'DataTableOptions'; + + if (!$this->model->methodExists($methodName) && !$this->model->methodExists('getDataTableOptions')) { + throw new ApplicationException( + Lang::get( + 'backend::lang.model.missing_method', + [ + 'class' => get_class($this->model), + 'method' => 'getDataTableOptions' + ] + ) + ); + } + + if ($this->model->methodExists($methodName)) { + $result = $this->model->$methodName($columnName, $rowData); + } else { + $result = $this->model->getDataTableOptions($this->fieldName, $columnName, $rowData); + } + + if (!is_array($result)) { + $result = []; + } + + return $result; + } +} diff --git a/modules/backend/formwidgets/DatePicker.php b/modules/backend/formwidgets/DatePicker.php new file mode 100644 index 0000000..893c961 --- /dev/null +++ b/modules/backend/formwidgets/DatePicker.php @@ -0,0 +1,207 @@ +fillFromConfig([ + 'format', + 'mode', + 'minDate', + 'maxDate', + 'yearRange', + 'firstDay', + 'showWeekNumber', + 'ignoreTimezone', + ]); + + $this->mode = strtolower($this->mode); + + if ($this->minDate !== null) { + $this->minDate = is_int($this->minDate) + ? Carbon::createFromTimestamp($this->minDate) + : Carbon::parse($this->minDate); + } + + if ($this->maxDate !== null) { + $this->maxDate = is_int($this->maxDate) + ? Carbon::createFromTimestamp($this->maxDate) + : Carbon::parse($this->maxDate); + } + } + + /** + * @inheritDoc + */ + public function render() + { + try { + $this->prepareVars(); + } catch (ApplicationException $ex) { + $this->vars['error'] = $ex->getMessage(); + } + + return $this->makePartial('datepicker'); + } + + /** + * Prepares the list data + */ + public function prepareVars() + { + if ($value = $this->getLoadValue()) { + $value = DateTimeHelper::makeCarbon($value, false); + + if (!($value instanceof Carbon)) { + $this->vars['error'] = (sprintf('"%s" is not a valid date / time value.', $value)); + } else { + if ($this->mode === 'date' && !$this->ignoreTimezone) { + $backendTimeZone = \Backend\Models\Preference::get('timezone'); + $value->setTimezone($backendTimeZone); + $value->setTime(0, 0, 0); + $value->setTimezone(Config::get('app.timezone')); + } + $value = $value->toDateTimeString(); + } + } + + // Disable the datepicker visually when readOnly is enabled + if ($this->formField->readOnly) { + $this->formField->disabled = true; + } + + $this->vars['name'] = $this->getFieldName(); + $this->vars['value'] = $value ?: ''; + $this->vars['field'] = $this->formField; + $this->vars['mode'] = $this->mode; + $this->vars['minDate'] = $this->minDate; + $this->vars['maxDate'] = $this->maxDate; + $this->vars['yearRange'] = $this->yearRange; + $this->vars['firstDay'] = $this->firstDay; + $this->vars['showWeekNumber'] = $this->showWeekNumber; + $this->vars['ignoreTimezone'] = $this->ignoreTimezone; + $this->vars['format'] = $this->format; + $this->vars['formatMoment'] = $this->getDateFormatMoment(); + $this->vars['formatAlias'] = $this->getDateFormatAlias(); + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + if ($this->formField->disabled || $this->formField->hidden) { + return FormField::NO_SAVE_DATA; + } + + if (!strlen($value)) { + return null; + } + + return $value; + } + + /** + * Convert PHP format to JS format + */ + protected function getDateFormatMoment() + { + if ($this->format) { + return DateTimeHelper::momentFormat($this->format); + } + } + + /* + * Display alias, used by preview mode + */ + protected function getDateFormatAlias() + { + if ($this->format) { + return null; + } + + if ($this->mode == 'time') { + return 'time'; + } + elseif ($this->mode == 'date') { + return 'dateLong'; + } + else { + return 'dateTimeLong'; + } + } +} diff --git a/modules/backend/formwidgets/FieldSet.php b/modules/backend/formwidgets/FieldSet.php new file mode 100644 index 0000000..70da8e0 --- /dev/null +++ b/modules/backend/formwidgets/FieldSet.php @@ -0,0 +1,102 @@ + + */ +class FieldSet extends FormWidgetBase +{ + /** + * @inheritDoc + */ + protected $defaultAlias = 'fieldset'; + + /** + * @var array Field configuration + */ + public $fields; + + /** + * @var bool Determines if this form field should display comments and labels. + */ + public $showLabels = false; + + /** + * @var Form form widget reference + */ + protected $formWidget; + + /** + * @inheritDoc + */ + public function init() + { + $this->fillFromConfig([ + 'fields', + ]); + + if ($this->formField->disabled) { + $this->previewMode = true; + } + + $config = $this->makeConfig(['fields' => $this->fields]); + $config->model = $this->model; + $config->data = $this->getLoadValue(); + $config->alias = $this->alias . $this->defaultAlias; + // set arrayName from parent form to save fields to the model + $config->arrayName = $this->getParentForm()->arrayName; + $config->isNested = true; + + $widget = $this->formWidget = $this->makeWidget(Form::class, $config); + $widget->previewMode = $this->previewMode; + $widget->bindToController(); + } + + protected function loadAssets() + { + $this->addCss('css/fieldset.css', 'core'); + } + + /** + * Returns the save data for the nested fields, to be merged into the parent + * form's data as if these fields were defined at that level. Reusing the nested + * form's getSaveData() ensures number casting, widget getSaveValue() handling, + * NO_SAVE_DATA exclusion and disabled/hidden skipping all behave identically to + * a regular field. + */ + public function getSaveData(): array + { + return $this->formWidget->getSaveData(); + } + + /** + * @inheritdoc + */ + public function render() + { + $this->prepareVars(); + return $this->makePartial('fieldset'); + } + + public function prepareVars() + { + $this->formWidget->previewMode = $this->previewMode; + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + return FormField::NO_SAVE_DATA; + } +} diff --git a/modules/backend/formwidgets/FileUpload.php b/modules/backend/formwidgets/FileUpload.php new file mode 100644 index 0000000..1d6cc8f --- /dev/null +++ b/modules/backend/formwidgets/FileUpload.php @@ -0,0 +1,561 @@ + 'crop', + 'extension' => 'auto' + ]; + + /** + * @var boolean Allow the user to set a caption. + */ + public $useCaption = true; + + /** + * @var boolean Automatically attaches the uploaded file on upload if the parent record exists instead of using deferred binding to attach on save of the parent record. Defaults to false. + */ + public $attachOnUpload = false; + + // + // Object properties + // + + /** + * @inheritDoc + */ + protected $defaultAlias = 'fileupload'; + + /** + * @var Form The embedded form for modifying the properties of the selected file + */ + protected $configFormWidget; + + /** + * @inheritDoc + */ + public function init() + { + $this->maxFilesize = $this->getUploadMaxFilesize(); + + $this->fillFromConfig([ + 'iconClass', + 'prompt', + 'imageWidth', + 'imageHeight', + 'fileTypes', + 'maxFilesize', + 'mimeTypes', + 'thumbOptions', + 'useCaption', + 'attachOnUpload', + ]); + + $this->iconClass = $this->iconClass ?? 'icon-upload'; + + if ($this->formField->disabled) { + $this->previewMode = true; + } + + $this->getConfigFormWidget(); + } + + /** + * @inheritDoc + */ + public function render() + { + $this->prepareVars(); + return $this->makePartial('fileupload'); + } + + /** + * Prepares the view data + */ + protected function prepareVars() + { + if ($this->formField->disabled) { + $this->previewMode = true; + } + + if ($this->previewMode) { + $this->useCaption = false; + } + + if ($this->maxFilesize > $this->getUploadMaxFilesize()) { + throw new ApplicationException('Maximum allowed size for uploaded files: ' . $this->getUploadMaxFilesize()); + } + + $this->vars['fileList'] = $fileList = $this->getFileList(); + $this->vars['singleFile'] = $fileList->first(); + $this->vars['displayMode'] = $this->getDisplayMode(); + $this->vars['emptyIcon'] = $this->getConfig('emptyIcon', 'icon-upload'); + $this->vars['imageHeight'] = $this->imageHeight; + $this->vars['imageWidth'] = $this->imageWidth; + $this->vars['acceptedFileTypes'] = $this->getAcceptedFileTypes(true); + $this->vars['maxFilesize'] = $this->maxFilesize; + $this->vars['cssDimensions'] = $this->getCssDimensions(); + $this->vars['cssBlockDimensions'] = $this->getCssDimensions('block'); + $this->vars['useCaption'] = $this->useCaption; + $this->vars['iconClass'] = $this->iconClass; + $this->vars['prompt'] = $this->getPromptText(); + } + + /** + * Get the file record for this request, returns false if none available + * + * @return File|false + */ + protected function getFileRecord() + { + $record = false; + + if (!empty(post('file_id'))) { + // Scope the lookup to this widget's own relation (including any files + // bound via the current deferred-binding session) so that an + // attacker-controlled file_id cannot reference an arbitrary + // System\Models\File record belonging to another model. See + // GHSA-3277-h8g9-qj5f. + $record = $this->getRelationObject() + ->withDeferred($this->sessionKey) + ->find(post('file_id')) ?: false; + } + + return $record; + } + + /** + * Get the instantiated config Form widget + */ + public function getConfigFormWidget(): Form + { + if ($this->configFormWidget) { + return $this->configFormWidget; + } + + $config = $this->makeConfig('~/modules/system/models/file/fields.yaml'); + $config->model = $this->getFileRecord() ?: $this->getRelationModel(); + $config->alias = $this->alias . $this->defaultAlias; + $config->arrayName = $this->getFieldName(); + + $widget = $this->makeWidget(Form::class, $config); + $widget->bindToController(); + + return $this->configFormWidget = $widget; + } + + protected function getFileList() + { + $list = $this + ->getRelationObject() + ->withDeferred($this->sessionKey) + ->orderBy('sort_order') + ->get() + ; + + /* + * Decorate each file with thumb and custom download path + */ + $list->each(function ($file) { + $this->decorateFileAttributes($file); + }); + + return $list; + } + + /** + * Returns the display mode for the file upload. Eg: file-multi, image-single, etc. + */ + protected function getDisplayMode(): string + { + $mode = $this->getConfig('mode', 'image'); + + if (str_contains($mode, '-')) { + return $mode; + } + + $relationType = $this->getRelationType(); + $mode .= ($relationType === 'attachMany' || $relationType === 'morphMany') ? '-multi' : '-single'; + + return $mode; + } + + /** + * Returns the escaped and translated prompt text to display according to the type. + */ + protected function getPromptText(): string + { + if ($this->prompt === null) { + $isMulti = ends_with($this->getDisplayMode(), 'multi'); + $this->prompt = $isMulti + ? 'backend::lang.fileupload.upload_file' + : 'backend::lang.fileupload.default_prompt'; + } + + $uploadIconStr = sprintf('', $this->iconClass); + return str_replace('%s', $uploadIconStr, e(trans($this->prompt))); + } + + /** + * Returns the CSS dimensions for the uploaded image, + * uses auto where no dimension is provided. + */ + protected function getCssDimensions(?string $mode = null): string + { + if (!$this->imageWidth && !$this->imageHeight) { + return ''; + } + + $cssDimensions = ''; + + if ($mode == 'block') { + $cssDimensions .= $this->imageWidth + ? 'width: ' . $this->imageWidth . 'px;' + : 'width: ' . $this->imageHeight . 'px;'; + + $cssDimensions .= ($this->imageHeight) + ? 'max-height: ' . $this->imageHeight . 'px;' + : 'height: auto;'; + } else { + $cssDimensions .= $this->imageWidth + ? 'width: ' . $this->imageWidth . 'px;' + : 'width: auto;'; + + $cssDimensions .= ($this->imageHeight) + ? 'max-height: ' . $this->imageHeight . 'px;' + : 'height: auto;'; + } + + return $cssDimensions; + } + + /** + * Returns the specified accepted file types, or the default + * based on the mode. Image mode will return: + * - jpg,jpeg,bmp,png,gif,svg + * @return string + */ + public function getAcceptedFileTypes($includeDot = false) + { + $types = $this->fileTypes; + + if ($types === false) { + $isImage = starts_with($this->getDisplayMode(), 'image'); + $types = implode(',', FileDefinitions::get($isImage ? 'imageExtensions' : 'defaultExtensions')); + } + + if (!$types || $types == '*') { + return null; + } + + if (!is_array($types)) { + $types = explode(',', $types); + } + + $types = array_map(function ($value) use ($includeDot) { + $value = trim($value); + + if (substr($value, 0, 1) == '.') { + $value = substr($value, 1); + } + + if ($includeDot) { + $value = '.'.$value; + } + + return $value; + }, $types); + + return implode(',', $types); + } + + /** + * Removes a file attachment. + */ + public function onRemoveAttachment(): void + { + if ($file = $this->getFileRecord()) { + $this->getRelationObject()->remove($file, $this->sessionKey); + } + } + + /** + * Sorts file attachments. + * + * Expects (array) sortOrder [$fileId => $fileOrder] in the POST data. + */ + public function onSortAttachments(): void + { + if ($sortData = post('sortOrder')) { + // Only reorder files that actually belong to this widget's relation + // (including the current deferred-binding session), never arbitrary + // System\Models\File rows referenced by a posted id. See + // GHSA-3277-h8g9-qj5f. + $keyName = $this->getRelationModel()->getKeyName(); + $validIds = $this->getRelationObject() + ->withDeferred($this->sessionKey) + ->pluck($keyName) + ->all(); + + $sortData = array_intersect_key($sortData, array_flip($validIds)); + if (empty($sortData)) { + return; + } + + $ids = array_keys($sortData); + $orders = array_values($sortData); + + $this->getRelationModel()->setSortableOrder($ids, $orders); + } + } + + /** + * Loads the configuration form for an attachment, allowing title and description to be set. + * + * @throws ApplicationException if unable to find the file record + */ + public function onLoadAttachmentConfig(): string + { + if ($file = $this->getFileRecord()) { + $file = $this->decorateFileAttributes($file); + + $this->vars['file'] = $file; + $this->vars['displayMode'] = $this->getDisplayMode(); + $this->vars['cssDimensions'] = $this->getCssDimensions(); + $this->vars['parentElementId'] = $this->getId(); + + return $this->makePartial('config_form'); + } + + throw new ApplicationException('Unable to find file, it may no longer exist'); + } + + /** + * Commit the changes of the attachment configuration form. + */ + public function onSaveAttachmentConfig() + { + try { + $formWidget = $this->getConfigFormWidget(); + if ($file = $formWidget->model) { + $modelsToSave = $this->prepareModelsToSave($file, $formWidget->getSaveData()); + Db::transaction(function () use ($modelsToSave, $formWidget) { + foreach ($modelsToSave as $modelToSave) { + $modelToSave->save(null, $formWidget->getSessionKey()); + } + }); + + return ['displayName' => $file->title ?: $file->file_name]; + } + + throw new ApplicationException('Unable to find file, it may no longer exist'); + } + catch (Exception $ex) { + return json_encode(['error' => $ex->getMessage()]); + } + } + + /** + * @inheritDoc + */ + protected function loadAssets() + { + $this->addCss('css/fileupload.css', 'core'); + $this->addJs('js/fileupload.js', 'core'); + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + return FormField::NO_SAVE_DATA; + } + + /** + * Upload handler for the server-side processing of uploaded files + */ + public function onUpload() + { + try { + $file = $this->getRelationModel(); + $fileRelation = $this->getRelationObject(); + $file->is_public = $fileRelation->isPublic(); + + /** + * @event backend.formwidgets.fileupload.onUpload + * Provides an opportunity to process the file upload using custom logic. + * + * Example usage () + */ + if (!($data = Event::fire('backend.formwidgets.fileupload.onUpload', [$this, $file], true))) { + if (!Input::hasFile('file_data')) { + throw new ApplicationException('File missing from request'); + } + + $validationRules = ['max:'.$file::getMaxFilesize()]; + $data = Input::file('file_data'); + + if (!$data->isValid()) { + throw new ApplicationException('File is not valid'); + } + + if ($fileTypes = $this->getAcceptedFileTypes()) { + $validationRules[] = 'extensions:'.$fileTypes; + } + + if ($this->mimeTypes) { + $validationRules[] = 'mimes:'.$this->mimeTypes; + } + + $validation = Validator::make( + ['file_data' => $data], + ['file_data' => $validationRules] + ); + + if ($validation->fails()) { + throw new ValidationException($validation); + } + } + + $file->data = $data; + $file->save(); + + /** + * Attach directly to the parent model if it exists and attachOnUpload has been set to true + * else attach via deferred binding + */ + $parent = $fileRelation->getParent(); + if ($this->attachOnUpload && $parent && $parent->exists) { + $fileRelation->add($file); + } + else { + $fileRelation->add($file, $this->sessionKey); + } + + $file = $this->decorateFileAttributes($file); + + $result = [ + 'id' => $file->id, + 'thumb' => $file->thumbUrl, + 'path' => $file->pathUrl + ]; + + $response = Response::make($result, 200); + } + catch (Exception $ex) { + $response = Response::make($ex->getMessage(), 400); + } + + return $response; + } + + /** + * Adds the bespoke attributes used internally by this widget. + * - thumbUrl + * - pathUrl + * @return System\Models\File + */ + protected function decorateFileAttributes($file) + { + $path = $thumb = $file->getPath(); + + if ($this->imageWidth || $this->imageHeight) { + $thumb = $file->getThumb($this->imageWidth, $this->imageHeight, $this->thumbOptions); + } + + $file->pathUrl = $path; + $file->thumbUrl = $thumb; + + return $file; + } + + /** + * Return max upload filesize in Mb + * @return integer + */ + protected function getUploadMaxFilesize() + { + $size = ini_get('upload_max_filesize'); + if (preg_match('/^([\d\.]+)([KMG])$/i', $size, $match)) { + $pos = array_search(strtoupper($match[2]), ['K', 'M', 'G']); + if ($pos !== false) { + $size = $match[1] * pow(1024, $pos + 1); + } + } + return floor($size / 1024 / 1024); + } +} diff --git a/modules/backend/formwidgets/IconPicker.php b/modules/backend/formwidgets/IconPicker.php new file mode 100644 index 0000000..33eafc6 --- /dev/null +++ b/modules/backend/formwidgets/IconPicker.php @@ -0,0 +1,59 @@ +prepareVars(); + return $this->makePartial('iconpicker'); + } + + /** + * Prepares the list data + */ + public function prepareVars() + { + $this->vars['field'] = $this; + } + + /** + * @inheritDoc + */ + public function loadAssets(): void + { + $this->addJs('js/dist/iconpicker.js', 'core'); + } + + public function onLoadIconLibrary() + { + $libraries = $this->config->libraries ?? static::DEFAULT_LIBRARIES; + + if (is_string($libraries)) { + $libraries = Yaml::parseFile(File::symbolizePath($libraries)); + } + + return json_encode($libraries); + } +} diff --git a/modules/backend/formwidgets/MarkdownEditor.php b/modules/backend/formwidgets/MarkdownEditor.php new file mode 100644 index 0000000..105e0d5 --- /dev/null +++ b/modules/backend/formwidgets/MarkdownEditor.php @@ -0,0 +1,142 @@ +fillFromConfig([ + 'mode', + 'safe', + 'readOnly', + 'disabled', + ]); + } + + /** + * {@inheritDoc} + */ + public function render() + { + $this->prepareVars(); + return $this->makePartial('markdowneditor'); + } + + /** + * Prepares the widget data + */ + public function prepareVars() + { + $this->vars['mode'] = $this->mode; + $this->vars['stretch'] = $this->formField->stretch; + $this->vars['size'] = $this->formField->size; + $this->vars['name'] = $this->getFieldName(); + $this->vars['value'] = $this->getLoadValue(); + $this->vars['readOnly'] = $this->readOnly; + $this->vars['disabled'] = $this->disabled; + $this->vars['useMediaManager'] = BackendAuth::getUser()->hasAccess('media.manage_media'); + } + + /** + * {@inheritDoc} + */ + protected function loadAssets() + { + $this->addCss('css/markdowneditor.css', 'core'); + $this->addJs('js/markdowneditor.js', 'core'); + $this->addJs('/modules/backend/assets/vendor/ace-codeeditor/build-min.js', 'core'); + } + + /** + * Check to see if the generated HTML should be cleaned to remove any potential XSS + * + * @return boolean + */ + protected function shouldCleanHtml() + { + $user = BackendAuth::getUser(); + return !$user || !$user->hasAccess('backend.allow_unsafe_markdown'); + } + + /** + * {@inheritDoc} + */ + public function getSaveValue($value) + { + if ($this->shouldCleanHtml()) { + $value = Html::clean($value); + } + + return $value; + } + + /** + * AJAX handler to render the markdown as HTML + * + * @return array ['preview' => $generatedHTML] + */ + public function onRefresh() + { + $value = post($this->getFieldName()); + $previewHtml = $this->safe + ? Markdown::parseSafe($value) + : Markdown::parse($value); + + if ($this->shouldCleanHtml()) { + $previewHtml = Html::clean($previewHtml); + } + + return [ + 'preview' => $previewHtml + ]; + } +} diff --git a/modules/backend/formwidgets/MediaFinder.php b/modules/backend/formwidgets/MediaFinder.php new file mode 100644 index 0000000..ee3b707 --- /dev/null +++ b/modules/backend/formwidgets/MediaFinder.php @@ -0,0 +1,126 @@ +fillFromConfig([ + 'mode', + 'prompt', + 'imageWidth', + 'imageHeight' + ]); + + $user = BackendAuth::getUser(); + + if ($this->formField->disabled + || $this->formField->readOnly + || !$user + || !$user->hasAccess('media.manage_media') + ) { + $this->previewMode = true; + } + } + + /** + * @inheritDoc + */ + public function render() + { + $this->prepareVars(); + + return $this->makePartial('mediafinder'); + } + + /** + * Prepares the list data + */ + public function prepareVars() + { + $value = $this->getLoadValue(); + $isImage = $this->mode === 'image'; + + $this->vars['value'] = $value; + $this->vars['imageUrl'] = $isImage && $value ? MediaLibrary::url($value) : ''; + $this->vars['imageExists'] = $isImage && $value ? MediaLibrary::instance()->exists($value) : ''; + $this->vars['field'] = $this->formField; + $this->vars['prompt'] = str_replace('%s', '', trans($this->prompt)); + $this->vars['mode'] = $this->mode; + $this->vars['imageWidth'] = $this->imageWidth; + $this->vars['imageHeight'] = $this->imageHeight; + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + if ($this->formField->disabled || $this->formField->hidden) { + return FormField::NO_SAVE_DATA; + } + + return $value; + } + + /** + * @inheritDoc + */ + protected function loadAssets() + { + $this->addJs('js/mediafinder.js', 'core'); + $this->addCss('css/mediafinder.css', 'core'); + } +} diff --git a/modules/backend/formwidgets/NestedForm.php b/modules/backend/formwidgets/NestedForm.php new file mode 100644 index 0000000..c4479f5 --- /dev/null +++ b/modules/backend/formwidgets/NestedForm.php @@ -0,0 +1,85 @@ +fillFromConfig([ + 'form', + 'usePanelStyles', + ]); + + if ($this->formField->disabled) { + $this->previewMode = true; + } + + $config = $this->makeConfig($this->form); + $config->model = $this->model; + $config->data = $this->getLoadValue(); + $config->alias = $this->alias . $this->defaultAlias; + $config->arrayName = $this->getFieldName(); + $config->isNested = true; + + if (object_get($this->getParentForm()->config, 'enableDefaults') === true) { + $config->enableDefaults = true; + } + + $widget = $this->makeWidget(Form::class, $config); + $widget->previewMode = $this->previewMode; + $widget->bindToController(); + + $this->formWidget = $widget; + } + + protected function loadAssets() + { + $this->addCss('css/nestedform.css', 'core'); + } + + /** + * @inheritdoc + */ + public function render() + { + $this->prepareVars(); + return $this->makePartial('nestedform'); + } + + public function prepareVars() + { + $this->formWidget->previewMode = $this->previewMode; + } +} diff --git a/modules/backend/formwidgets/PermissionEditor.php b/modules/backend/formwidgets/PermissionEditor.php new file mode 100644 index 0000000..86edc6b --- /dev/null +++ b/modules/backend/formwidgets/PermissionEditor.php @@ -0,0 +1,171 @@ +fillFromConfig([ + 'mode', + 'availablePermissions', + ]); + + $this->user = BackendAuth::getUser(); + } + + /** + * @inheritDoc + */ + public function render() + { + $this->prepareVars(); + return $this->makePartial('permissioneditor'); + } + + /** + * Prepares the list data + */ + public function prepareVars() + { + if ($this->formField->disabled) { + $this->previewMode = true; + } + + $permissionsData = $this->formField->getValueFromData($this->model); + if (!is_array($permissionsData)) { + $permissionsData = []; + } + + $this->vars['mode'] = $this->mode; + $this->vars['permissions'] = $this->getFilteredPermissions(); + $this->vars['baseFieldName'] = $this->getFieldName(); + $this->vars['permissionsData'] = $permissionsData; + $this->vars['field'] = $this->formField; + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + if ($this->user->isSuperUser()) { + return is_array($value) ? $value : []; + } + + return $this->getSaveValueSecure($value); + } + + /** + * @inheritDoc + */ + protected function loadAssets() + { + $this->addCss('css/permissioneditor.css', 'core'); + $this->addJs('js/permissioneditor.js', 'core'); + } + + /** + * Returns a safely parsed set of permissions, ensuring the user cannot elevate + * their own permissions or permissions of another user above their own. + * + * @param string $value + * @return array + */ + protected function getSaveValueSecure($value) + { + $newPermissions = is_array($value) ? array_map('intval', $value) : []; + + if (!empty($newPermissions)) { + $existingPermissions = $this->model->permissions ?: []; + + $allowedPermissions = array_map(function ($permissionObject) { + return $permissionObject->code; + }, array_flatten($this->getFilteredPermissions())); + + foreach ($newPermissions as $permission => $code) { + if (in_array($permission, $allowedPermissions)) { + $existingPermissions[$permission] = $code; + } + } + + $newPermissions = $existingPermissions; + } + + return $newPermissions; + } + + /** + * Returns the available permissions; removing those that the logged-in user does not have access to + * + * @return array The permissions that the logged-in user does have access to ['permission-tab' => $arrayOfAllowedPermissionObjects] + */ + protected function getFilteredPermissions() + { + $permissions = BackendAuth::listTabbedPermissions(); + + foreach ($permissions as $tab => $permissionsArray) { + foreach ($permissionsArray as $index => $permission) { + if (!$this->user->hasAccess($permission->code) || + ( + is_array($this->availablePermissions) && + !in_array($permission->code, $this->availablePermissions) + )) { + unset($permissionsArray[$index]); + } + } + + if (empty($permissionsArray)) { + unset($permissions[$tab]); + } + else { + $permissions[$tab] = $permissionsArray; + } + } + + return $permissions; + } +} diff --git a/modules/backend/formwidgets/RecordFinder.php b/modules/backend/formwidgets/RecordFinder.php new file mode 100644 index 0000000..0e5799c --- /dev/null +++ b/modules/backend/formwidgets/RecordFinder.php @@ -0,0 +1,380 @@ +fillFromConfig([ + 'title', + 'prompt', + 'keyFrom', + 'nameFrom', + 'descriptionFrom', + 'scope', + 'conditions', + 'searchMode', + 'searchScope', + 'recordsPerPage', + 'useRelation', + 'modelClass', + ]); + + if (!isset($this->prompt)) { + $this->prompt = Lang::get('backend::lang.recordfinder.default_prompt'); + } + + if (!$this->useRelation && !class_exists($this->modelClass)) { + throw new ApplicationException(Lang::get('backend::lang.recordfinder.invalid_model_class', ['modelClass' => $this->modelClass])); + } + + $modelKey = $this->getRecordModel()->getKeyName(); + if ($this->keyFrom === 'id' && $modelKey !== 'id') { + $this->keyFrom = $modelKey; + } + + if (post('recordfinder_flag')) { + $this->listWidget = $this->makeListWidget(); + $this->listWidget->bindToController(); + + $this->searchWidget = $this->makeSearchWidget(); + $this->searchWidget->bindToController(); + + $this->listWidget->setSearchTerm($this->searchWidget->getActiveTerm()); + + /* + * Link the Search Widget to the List Widget + */ + $this->searchWidget->bindEvent('search.submit', function () { + $this->listWidget->setSearchTerm($this->searchWidget->getActiveTerm()); + return $this->listWidget->onRefresh(); + }); + } + } + + /** + * @inheritDoc + */ + public function render() + { + $this->prepareVars(); + return $this->makePartial('container'); + } + + public function onRefresh() + { + $value = post($this->getFieldName()); + if ($this->useRelation) { + list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom); + $model->{$attribute} = $value; + } else { + $this->formField->value = $value; + } + + $this->prepareVars(); + return ['#'.$this->getId('container') => $this->makePartial('recordfinder')]; + } + + public function onClearRecord() + { + if ($this->useRelation) { + list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom); + $model->{$attribute} = null; + } else { + $this->formField->value = null; + } + + $this->prepareVars(); + return ['#'.$this->getId('container') => $this->makePartial('recordfinder')]; + } + + /** + * Prepares the list data + */ + public function prepareVars() + { + $this->relationModel = $this->getLoadValue(); + + if ($this->formField->disabled) { + $this->previewMode = true; + } + + $this->vars['value'] = $this->getKeyValue(); + $this->vars['field'] = $this->formField; + $this->vars['nameValue'] = $this->getNameValue(); + $this->vars['descriptionValue'] = $this->getDescriptionValue(); + $this->vars['listWidget'] = $this->listWidget; + $this->vars['searchWidget'] = $this->searchWidget; + $this->vars['title'] = $this->title; + $this->vars['prompt'] = str_replace('%s', '', e(trans($this->prompt))); + } + + /** + * @inheritDoc + */ + protected function loadAssets() + { + $this->addJs('js/recordfinder.js', 'core'); + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + return strlen($value) ? $value : null; + } + + /** + * @inheritDoc + */ + public function getLoadValue() + { + $value = null; + + if ($this->useRelation) { + list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom); + if ($model !== null) { + $value = $model->{$attribute}; + } + } else { + $value = $this->modelClass::where($this->keyFrom, parent::getLoadValue())->first(); + } + + return $value; + } + + public function getKeyValue() + { + if (!$this->relationModel) { + return null; + } + + return $this->useRelation ? + $this->relationModel->{$this->keyFrom} : + $this->formField->value; + } + + public function getNameValue() + { + if (!$this->relationModel || !$this->nameFrom) { + return null; + } + + return $this->relationModel->{$this->nameFrom}; + } + + public function getDescriptionValue() + { + if (!$this->relationModel || !$this->descriptionFrom) { + return null; + } + + return $this->relationModel->{$this->descriptionFrom}; + } + + public function onFindRecord() + { + $this->prepareVars(); + + // Attach the parent element ID to the popup + $this->vars['parentElementId'] = $this->getId('popupTrigger'); + + /* + * Purge the search term stored in session + */ + if ($this->searchWidget) { + $this->listWidget->setSearchTerm(null); + $this->searchWidget->setActiveTerm(null); + } + + return $this->makePartial('recordfinder_form'); + } + + /** + * Gets the base model instance used by this field + */ + protected function getRecordModel(): Model + { + $model = null; + if ($this->useRelation) { + $model = $this->getRelationModel(); + } else { + $model = new $this->modelClass; + } + return $model; + } + + protected function makeListWidget() + { + $config = $this->makeConfig($this->getConfig('list')); + + $config->model = $this->getRecordModel(); + $config->alias = $this->alias . 'List'; + $config->showSetup = false; + $config->showCheckboxes = false; + $config->recordsPerPage = $this->recordsPerPage; + $config->recordOnClick = sprintf("$('#%s').recordFinder('updateRecord', this, ':" . $this->keyFrom . "')", $this->getId()); + $widget = $this->makeWidget('Backend\Widgets\Lists', $config); + + $widget->setSearchOptions([ + 'mode' => $this->searchMode, + 'scope' => $this->searchScope, + ]); + + if ($sqlConditions = $this->conditions) { + $widget->bindEvent('list.extendQueryBefore', function ($query) use ($sqlConditions) { + $query->whereRaw($sqlConditions); + }); + } + elseif ($scopeMethod = $this->scope) { + $widget->bindEvent('list.extendQueryBefore', function ($query) use ($scopeMethod) { + $query->$scopeMethod($this->model); + }); + } + else { + if ($this->useRelation) { + $widget->bindEvent('list.extendQueryBefore', function ($query) { + $this->getRelationObject()->addDefinedConstraintsToQuery($query); + }); + } + } + + return $widget; + } + + protected function makeSearchWidget() + { + $config = $this->makeConfig(); + $config->alias = $this->alias . 'Search'; + $config->growable = false; + $config->prompt = 'backend::lang.list.search_prompt'; + $widget = $this->makeWidget('Backend\Widgets\Search', $config); + $widget->cssClasses[] = 'recordfinder-search'; + return $widget; + } +} diff --git a/modules/backend/formwidgets/Relation.php b/modules/backend/formwidgets/Relation.php new file mode 100644 index 0000000..830af3b --- /dev/null +++ b/modules/backend/formwidgets/Relation.php @@ -0,0 +1,198 @@ +fillFromConfig([ + 'nameFrom', + 'emptyOption', + 'scope', + 'order', + ]); + + if (isset($this->config->select)) { + $this->sqlSelect = $this->config->select; + } + } + + /** + * @inheritDoc + */ + public function render() + { + $this->prepareVars(); + return $this->makePartial('relation'); + } + + /** + * Prepares the view data + */ + public function prepareVars() + { + $this->vars['field'] = $this->makeRenderFormField(); + } + + /** + * Makes the form object used for rendering a simple field type + * @throws SystemException if an unsupported relation type is used. + */ + protected function makeRenderFormField() + { + return $this->renderFormField = RelationBase::noConstraints(function () { + + $field = clone $this->formField; + $relationObject = $this->getRelationObject(); + $query = $relationObject->newQuery(); + + list($model, $attribute) = $this->resolveModelAttribute($this->valueFrom); + $relationType = $model->getRelationType($attribute); + $relationModel = $model->makeRelation($attribute); + + if (in_array($relationType, ['belongsToMany', 'morphToMany', 'morphedByMany', 'hasMany'])) { + $field->type = 'checkboxlist'; + } elseif (in_array($relationType, ['belongsTo', 'hasOne'])) { + $field->type = 'dropdown'; + } else { + throw new SystemException( + Lang::get('backend::lang.relation.relationwidget_unsupported_type', [ + 'type' => $relationType + ]) + ); + } + + // Order query by the configured option. + if ($this->order) { + // Using "raw" to allow authors to use a string to define the order clause. + $query->orderByRaw($this->order); + } + + // It is safe to assume that if the model and related model are of + // the exact same class, then it cannot be related to itself + if ($model->exists && (get_class($model) == get_class($relationModel))) { + $query->where($relationModel->getKeyName(), '<>', $model->getKey()); + } + + // Even though "no constraints" is applied, belongsToMany constrains the query + // by joining its pivot table. Remove all joins from the query. + $query->getQuery()->getQuery()->joins = []; + + if ($scopeMethod = $this->scope) { + $query->$scopeMethod($model); + } + + // Determine if the model uses a tree trait + $treeTraits = ['Winter\Storm\Database\Traits\NestedTree', 'Winter\Storm\Database\Traits\SimpleTree']; + $usesTree = count(array_intersect($treeTraits, class_uses($relationModel))) > 0; + + // The "sqlSelect" config takes precedence over "nameFrom". + // A virtual column called "selection" will contain the result. + // Tree models must select all columns to return parent columns, etc. + if ($this->sqlSelect) { + $nameFrom = 'selection'; + $selectColumn = $usesTree ? '*' : $relationModel->getKeyName(); + $result = $query->select($selectColumn, Db::raw($this->sqlSelect . ' AS ' . $nameFrom)); + } + else { + $nameFrom = $this->nameFrom; + $result = $query->getQuery()->get(); + } + + // Some simpler relations can specify a custom local or foreign "other" key, + // which can be detected and implemented here automagically. + $primaryKeyName = in_array($relationType, ['hasMany', 'belongsTo', 'hasOne']) + ? $relationObject->getOtherKey() + : $relationModel->getKeyName(); + + $field->options = $usesTree + ? $result->listsNested($nameFrom, $primaryKeyName) + : $result->lists($nameFrom, $primaryKeyName); + + return $field; + }); + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + if ($this->formField->disabled || $this->formField->hidden) { + return FormField::NO_SAVE_DATA; + } + + if (is_string($value) && !strlen($value)) { + return null; + } + + if (is_array($value) && !count($value)) { + return null; + } + + return $value; + } +} diff --git a/modules/backend/formwidgets/RelationManager.php b/modules/backend/formwidgets/RelationManager.php new file mode 100644 index 0000000..b116588 --- /dev/null +++ b/modules/backend/formwidgets/RelationManager.php @@ -0,0 +1,84 @@ +fillFromConfig([ + 'readOnly', + 'recordUrl', + 'recordOnClick', + 'relation', + ]); + + if (!isset($this->readOnly) && $this->config->previewMode) { + $this->readOnly = $this->config->previewMode; + } + } + + public function render() + { + if (!$this->controller->isClassExtendedWith(\Backend\Behaviors\RelationController::class)) { + $error = Lang::get('backend::lang.relation.missing_behavior', [ + 'field' => $this->formField->fieldName, + 'controller' => get_class($this->controller), + ]); + throw new SystemException($error); + } + + $options = []; + + if (!is_null($this->readOnly)) { + $options['readOnly'] = $this->readOnly; + } + + if (!is_null($this->recordUrl)) { + $options['recordUrl'] = $this->recordUrl; + } + + if (!is_null($this->recordOnClick)) { + $options['recordOnClick'] = $this->recordOnClick; + } + + $relation = $this->relation ?: $this->formField->fieldName; + + return $this->controller->relationRender($relation, $options); + } + + public function getSaveValue($value) + { + return FormField::NO_SAVE_DATA; + } +} diff --git a/modules/backend/formwidgets/Repeater.php b/modules/backend/formwidgets/Repeater.php new file mode 100644 index 0000000..4e834c8 --- /dev/null +++ b/modules/backend/formwidgets/Repeater.php @@ -0,0 +1,535 @@ +fillFromConfig([ + 'form', + 'mode', + 'style', + 'prompt', + 'sortable', + 'titleFrom', + 'minItems', + 'maxItems', + 'columns', + 'rowHeight', + ]); + + if ($this->formField->disabled) { + $this->previewMode = true; + } + + if ($this->columns < 2 || $this->columns > 6) { + $this->columns = 4; + } + + // Check for loaded flag in POST + if ((bool) post($this->alias . '_loaded') === true) { + $this->loaded = true; + } + + $this->checkAddItemRequest(); + $this->processGroupMode(); + + if (!self::$onAddItemCalled) { + $this->processItems(); + } + } + + /** + * {@inheritDoc} + */ + public function render() + { + $this->prepareVars(); + return $this->makePartial('repeater'); + } + + /** + * Prepares the form widget view data + */ + public function prepareVars() + { + // Refresh the loaded data to support being modified by filterFields + // @see https://github.com/octobercms/october/issues/2613 + if (!self::$onAddItemCalled) { + $this->processItems(); + } + + if ($this->previewMode) { + foreach ($this->formWidgets as $widget) { + $widget->previewMode = true; + } + } + + $this->vars['prompt'] = $this->prompt; + $this->vars['mode'] = in_array($this->mode, ['list', 'grid']) ? $this->mode : 'list'; + $this->vars['formWidgets'] = $this->formWidgets; + $this->vars['titleFrom'] = $this->titleFrom; + $this->vars['minItems'] = (int) $this->minItems; + $this->vars['maxItems'] = (int) $this->maxItems; + $this->vars['sortable'] = (bool) $this->sortable; + $this->vars['style'] = in_array($this->style, ['default', 'collapsed', 'accordion']) ? $this->style : 'default'; + $this->vars['columns'] = (int) $this->columns; + $this->vars['rowHeight'] = (int) $this->rowHeight; + + $this->vars['useGroups'] = $this->useGroups; + $this->vars['groupDefinitions'] = $this->groupDefinitions; + } + + /** + * @inheritDoc + */ + protected function loadAssets() + { + $this->addCss('css/repeater.css', 'core'); + $this->addJs('js/repeater.js', 'core'); + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + return $this->processSaveValue($value); + } + + /** + * Splices in some meta data (group and index values) to the dataset. + * @param array $value + * @return array|null + */ + protected function processSaveValue($value) + { + if (!is_array($value) || !$value) { + return null; + } + + if ($this->minItems && count($value) < $this->minItems) { + throw new ApplicationException(Lang::get('backend::lang.repeater.min_items_failed', ['name' => $this->fieldName, 'min' => $this->minItems, 'items' => count($value)])); + } + if ($this->maxItems && count($value) > $this->maxItems) { + throw new ApplicationException(Lang::get('backend::lang.repeater.max_items_failed', ['name' => $this->fieldName, 'max' => $this->maxItems, 'items' => count($value)])); + } + + /* + * Give repeated form field widgets an opportunity to process the data. + */ + foreach ($value as $index => $data) { + if (isset($this->formWidgets[$index])) { + if ($this->useGroups) { + $value[$index] = array_merge($this->formWidgets[$index]->getSaveData(), ['_group' => $data['_group']]); + } else { + $value[$index] = $this->formWidgets[$index]->getSaveData(); + } + } + } + + return array_values($value); + } + + /** + * Processes form data and applies it to the form widgets. + * @return void + */ + protected function processItems() + { + $currentValue = ($this->loaded === true) + ? post($this->formField->getName()) + : $this->getLoadValue(); + + // Detect when a child widget is trying to run an AJAX handler + // outside of the form element that contains all the repeater + // fields that would normally be used to identify that case + $handler = $this->controller->getAjaxHandler(); + if (!$this->loaded && starts_with($handler, $this->alias . 'Form')) { + // Attempt to get the index of the repeater + $handler = str_after($handler, $this->alias . 'Form'); + preg_match("~^(\d+)~", $handler, $matches); + + if (isset($matches[1])) { + $index = $matches[1]; + $this->makeItemFormWidget($index); + } + } + + // Ensure that the minimum number of items are preinitialized + // ONLY DONE WHEN NOT IN GROUP MODE + if (!$this->useGroups && $this->minItems > 0) { + if (!is_array($currentValue)) { + $currentValue = []; + for ($i = 0; $i < $this->minItems; $i++) { + $currentValue[$i] = []; + } + } elseif (count($currentValue) < $this->minItems) { + for ($i = 0; $i < ($this->minItems - count($currentValue)); $i++) { + $currentValue[] = []; + } + } + } + + if (!$this->childAddItemCalled && $currentValue === null) { + $this->formWidgets = []; + return; + } + + if ($this->childAddItemCalled && !isset($currentValue[$this->childIndexCalled])) { + // If no value is available but a child repeater has added an item, add a "stub" repeater item + $this->makeItemFormWidget($this->childIndexCalled); + } + + if (!is_array($currentValue)) { + return; + } + + collect($currentValue)->each(function ($value, $index) { + $this->makeItemFormWidget($index, array_get($value, '_group', null)); + }); + } + + /** + * Creates a form widget based on a field index and optional group code. + * @param int $index + * @param string $index + * @return \Backend\Widgets\Form + */ + protected function makeItemFormWidget($index = 0, $groupCode = null) + { + $configDefinition = $this->useGroups + ? $this->getGroupFormFieldConfig($groupCode) + : $this->form; + + $config = $this->makeConfig($configDefinition); + $config->model = $this->model; + $config->data = $this->getValueFromIndex($index); + $config->alias = $this->alias . 'Form' . $index; + $config->arrayName = $this->getFieldName().'['.$index.']'; + $config->isNested = true; + if (self::$onAddItemCalled || $this->minItems > 0) { + $config->enableDefaults = true; + } + + $widget = $this->makeWidget('Backend\Widgets\Form', $config); + $widget->previewMode = $this->previewMode; + $widget->bindToController(); + + $this->indexMeta[$index] = [ + 'groupCode' => $groupCode + ]; + + return $this->formWidgets[$index] = $widget; + } + + /** + * Returns the data at a given index. + * @param int $index + */ + protected function getValueFromIndex($index) + { + $value = ($this->loaded === true) + ? post($this->formField->getName()) + : $this->getLoadValue(); + + if (!is_array($value)) { + $value = []; + } + + return array_get($value, $index, []); + } + + // + // AJAX handlers + // + + public function onAddItem() + { + $groupCode = post('_repeater_group'); + + $index = $this->getNextIndex(); + + $this->prepareVars(); + $this->vars['widget'] = $this->makeItemFormWidget($index, $groupCode); + $this->vars['indexValue'] = $index; + + $itemContainer = '@#' . $this->getId('items'); + $addItemContainer = '#' . $this->getId('add-item'); + + return [ + $addItemContainer => '', + $itemContainer => $this->makePartial('repeater_item') . $this->makePartial('repeater_add_item') + ]; + } + + public function onRemoveItem() + { + // Useful for deleting relations + } + + public function onRefresh() + { + $index = post('_repeater_index'); + $group = post('_repeater_group'); + + $widget = $this->makeItemFormWidget($index, $group); + + return $widget->onRefresh(); + } + + /** + * Determines the next available index number for assigning to a new repeater item. + * + * @return int + */ + protected function getNextIndex() + { + if ($this->loaded === true) { + $data = post($this->formField->getName()); + + if (is_array($data) && count($data)) { + return (max(array_keys($data)) + 1); + } + } else { + $data = $this->getLoadValue(); + + if (is_array($data)) { + return count($data); + } + } + + return 0; + } + + /** + * Determines the repeater that has triggered an AJAX request to add an item. + * + * @return void + */ + protected function checkAddItemRequest() + { + $handler = $this->getParentForm() + ->getController() + ->getAjaxHandler(); + + if ($handler === null || strpos($handler, '::') === false) { + return; + } + + list($widgetName, $handlerName) = explode('::', $handler); + if ($handlerName !== 'onAddItem') { + return; + } + + if ($this->alias === $widgetName) { + // This repeater has made the AJAX request + self::$onAddItemCalled = true; + } else if (strpos($widgetName, $this->alias . 'Form') === 0) { + // A child repeater has made the AJAX request + + // Get index from AJAX handler + $handlerSuffix = str_replace($this->alias . 'Form', '', $widgetName); + if (preg_match('/^[0-9]+/', $handlerSuffix, $matches)) { + $this->childAddItemCalled = true; + $this->childIndexCalled = (int) $matches[0]; + } + } + } + + // + // Group mode + // + + /** + * Returns the form field configuration for a group, identified by code. + * @param string $code + * @return array|null + */ + protected function getGroupFormFieldConfig($code) + { + if (!$code) { + return null; + } + + $fields = array_get($this->groupDefinitions, $code.'.fields'); + + if (!$fields) { + return null; + } + + return ['fields' => $fields, 'enableDefaults' => object_get($this->config, 'enableDefaults')]; + } + + /** + * Process features related to group mode. + * @return void + */ + protected function processGroupMode() + { + $palette = []; + + if (!$group = $this->getConfig('groups', [])) { + $this->useGroups = false; + return; + } + + if (is_string($group)) { + $group = $this->makeConfig($group); + } + + foreach ($group as $code => $config) { + $palette[$code] = [ + 'code' => $code, + 'name' => array_get($config, 'name'), + 'icon' => array_get($config, 'icon', 'icon-square-o'), + 'description' => array_get($config, 'description'), + 'fields' => array_get($config, 'fields') + ]; + } + + $this->groupDefinitions = $palette; + $this->useGroups = true; + } + + /** + * Returns a field group code from its index. + * @param $index int + * @return string + */ + public function getGroupCodeFromIndex($index) + { + return array_get($this->indexMeta, $index.'.groupCode'); + } + + /** + * Returns the group title from its unique code. + * @param $groupCode string + * @return string + */ + public function getGroupTitle($groupCode) + { + return array_get($this->groupDefinitions, $groupCode.'.name'); + } +} diff --git a/modules/backend/formwidgets/RichEditor.php b/modules/backend/formwidgets/RichEditor.php new file mode 100644 index 0000000..02c9949 --- /dev/null +++ b/modules/backend/formwidgets/RichEditor.php @@ -0,0 +1,315 @@ +formField->disabled) { + $this->readOnly = true; + } + + $this->fillFromConfig([ + 'fullPage', + 'readOnly', + 'toolbarButtons', + ]); + } + + /** + * @inheritDoc + */ + public function render() + { + $this->prepareVars(); + return $this->makePartial('richeditor'); + } + + /** + * Prepares the list data + */ + public function prepareVars() + { + $this->vars['field'] = $this->formField; + $this->vars['editorLang'] = $this->getValidEditorLang(); + $this->vars['fullPage'] = $this->fullPage; + $this->vars['stretch'] = $this->formField->stretch; + $this->vars['size'] = $this->formField->size; + $this->vars['readOnly'] = $this->readOnly; + $this->vars['name'] = $this->getFieldName(); + $this->vars['value'] = $this->getLoadValue(); + $this->vars['toolbarButtons'] = $this->evalToolbarButtons(); + $this->vars['useMediaManager'] = BackendAuth::getUser()->hasAccess('media.manage_media'); + + $this->vars['globalToolbarButtons'] = EditorSetting::getConfigured('html_toolbar_buttons'); + $this->vars['allowEmptyTags'] = EditorSetting::getConfigured('html_allow_empty_tags'); + $this->vars['allowTags'] = EditorSetting::getConfigured('html_allow_tags'); + $this->vars['allowAttributes'] = EditorSetting::getConfigured('html_allow_attributes'); + $this->vars['noWrapTags'] = EditorSetting::getConfigured('html_no_wrap_tags'); + $this->vars['removeTags'] = EditorSetting::getConfigured('html_remove_tags'); + $this->vars['lineBreakerTags'] = EditorSetting::getConfigured('html_line_breaker_tags'); + + $this->vars['imageStyles'] = EditorSetting::getConfiguredStyles('html_style_image'); + $this->vars['linkStyles'] = EditorSetting::getConfiguredStyles('html_style_link'); + $this->vars['paragraphStyles'] = EditorSetting::getConfiguredStyles('html_style_paragraph'); + $this->vars['paragraphFormats'] = EditorSetting::getConfiguredFormats('html_paragraph_formats'); + $this->vars['tableStyles'] = EditorSetting::getConfiguredStyles('html_style_table'); + $this->vars['tableCellStyles'] = EditorSetting::getConfiguredStyles('html_style_table_cell'); + } + + /** + * Determine the toolbar buttons to use based on config. + * @return string + */ + protected function evalToolbarButtons() + { + $buttons = $this->toolbarButtons; + + if (is_string($buttons)) { + $buttons = array_map(function ($button) { + return strlen($button) ? $button : '|'; + }, explode('|', $buttons)); + } + + return $buttons; + } + + public function onLoadPageLinksForm() + { + $this->vars['links'] = $this->getPageLinksArray(); + return $this->makePartial('page_links_form'); + } + + /** + * @inheritDoc + */ + protected function loadAssets() + { + $this->addCss('css/richeditor.css', 'core'); + $this->addJs('js/build-min.js', 'core'); + + if (Config::get('develop.decompileBackendAssets', false)) { + $scripts = Backend::decompileAsset($this->getAssetPath('js/build-plugins.js')); + foreach ($scripts as $script) { + $this->addJs($script, 'core'); + } + } else { + $this->addJs('js/build-plugins-min.js', 'core'); + } + + $this->addJs('/modules/backend/assets/vendor/ace-codeeditor/build-min.js', 'core'); + + if ($lang = $this->getValidEditorLang()) { + $this->addJs('vendor/froala/js/languages/'.$lang.'.js', 'core'); + } + } + + /** + * Returns a valid language code for Redactor. + * @return string|mixed + */ + protected function getValidEditorLang() + { + $locale = App::getLocale(); + + // English is baked in + if ($locale == 'en') { + return null; + } + + $locale = str_replace('-', '_', strtolower($locale)); + $path = base_path('modules/backend/formwidgets/richeditor/assets/vendor/froala/js/languages/'.$locale.'.js'); + + return File::exists($path) ? $locale : false; + } + + /** + * Returns a list of registered page link types. + * This is reserved functionality for separating the links by type. + * @return array Returns an array of registered page link types + */ + protected function getPageLinkTypes() + { + $result = []; + + /** + * @event backend.richeditor.listTypes + * Register additional "page link types" to the RichEditor FormWidget + * + * Example usage: + * + * Event::listen('backend.richeditor.listTypes', function () { + * return [ + * 'my-identifier' => 'author.plugin::lang.richeditor.link_types.my_identifier', + * ]; + * }); + * + */ + $apiResult = Event::fire('backend.richeditor.listTypes'); + if (is_array($apiResult)) { + foreach ($apiResult as $typeList) { + if (!is_array($typeList)) { + continue; + } + + foreach ($typeList as $typeCode => $typeName) { + $result[$typeCode] = $typeName; + } + } + } + + return $result; + } + + protected function getPageLinks($type) + { + $result = []; + + /** + * @event backend.richeditor.getTypeInfo + * Register additional "page link types" to the RichEditor FormWidget + * + * Example usage: + * + * Event::listen('backend.richeditor.getTypeInfo', function ($type) { + * if ($type === 'my-identifier') { + * return [ + * 'https://example.com/page1' => 'Page 1', + * 'https://example.com/parent-page' => [ + * 'title' => 'Parent Page', + * 'links' => [ + * 'https://example.com/child-page' => 'Child Page', + * ], + * ], + * ]; + * } + * }); + * + */ + $apiResult = Event::fire('backend.richeditor.getTypeInfo', [$type]); + if (is_array($apiResult)) { + foreach ($apiResult as $typeInfo) { + if (!is_array($typeInfo)) { + continue; + } + + foreach ($typeInfo as $name => $value) { + $result[$name] = $value; + } + } + } + + return $result; + } + + /** + * Returns a single collection of available page links. + * This implementation has room to place links under + * different groups based on the link type. + * @return array + */ + protected function getPageLinksArray() + { + $links = []; + $types = $this->getPageLinkTypes(); + + $links[] = ['name' => Lang::get('backend::lang.pagelist.select_page'), 'url' => false]; + + $iterator = function ($links, $level = 0) use (&$iterator) { + $result = []; + + foreach ($links as $linkUrl => $link) { + /* + * Remove scheme and host from URL + */ + $baseUrl = Request::getSchemeAndHttpHost(); + if (strpos($linkUrl, $baseUrl) === 0) { + $linkUrl = substr($linkUrl, strlen($baseUrl)); + } + + /* + * Root page fallback. + */ + if (strlen($linkUrl) === 0) { + $linkUrl = '/'; + } + + $linkName = str_repeat(' ', $level * 4); + $linkName .= is_array($link) ? array_get($link, 'title', '') : $link; + $result[] = ['name' => $linkName, 'url' => $linkUrl]; + + if (is_array($link)) { + $result = array_merge( + $result, + $iterator(array_get($link, 'links', []), $level + 1) + ); + } + } + + return $result; + }; + + foreach ($types as $typeCode => $typeName) { + $links = array_merge($links, $iterator($this->getPageLinks($typeCode))); + } + + return $links; + } +} diff --git a/modules/backend/formwidgets/Sensitive.php b/modules/backend/formwidgets/Sensitive.php new file mode 100644 index 0000000..8ab91b8 --- /dev/null +++ b/modules/backend/formwidgets/Sensitive.php @@ -0,0 +1,116 @@ +fillFromConfig([ + 'readOnly', + 'disabled', + 'allowCopy', + 'hiddenPlaceholder', + 'hideOnTabChange', + ]); + + if ($this->formField->disabled || $this->formField->readOnly) { + $this->previewMode = true; + } + } + + /** + * @inheritDoc + */ + public function render() + { + $this->prepareVars(); + + return $this->makePartial('sensitive'); + } + + /** + * Prepares the view data for the widget partial. + */ + public function prepareVars() + { + $this->vars['readOnly'] = $this->readOnly; + $this->vars['disabled'] = $this->disabled; + $this->vars['hasValue'] = !empty($this->getLoadValue()); + $this->vars['allowCopy'] = $this->allowCopy; + $this->vars['hiddenPlaceholder'] = $this->hiddenPlaceholder; + $this->vars['hideOnTabChange'] = $this->hideOnTabChange; + } + + /** + * Reveals the value of a hidden, unmodified sensitive field. + * + * @return array + */ + public function onShowValue() + { + return [ + 'value' => $this->getLoadValue() + ]; + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + if ($value === $this->hiddenPlaceholder) { + $value = $this->getLoadValue(); + } + + return $value; + } + + /** + * @inheritDoc + */ + protected function loadAssets() + { + $this->addJs('js/dist/sensitive.js', 'core'); + } +} diff --git a/modules/backend/formwidgets/TagList.php b/modules/backend/formwidgets/TagList.php new file mode 100644 index 0000000..620fde1 --- /dev/null +++ b/modules/backend/formwidgets/TagList.php @@ -0,0 +1,242 @@ +fillFromConfig([ + 'separator', + 'customTags', + 'options', + 'mode', + 'nameFrom', + 'useKey', + 'placeholder' + ]); + } + + /** + * @inheritDoc + */ + public function render() + { + $this->prepareVars(); + + return $this->makePartial('taglist'); + } + + /** + * Prepares the form widget view data + */ + public function prepareVars() + { + $this->vars['placeholder'] = $this->placeholder; + $this->vars['useKey'] = $this->useKey; + $this->vars['field'] = $this->formField; + $this->vars['fieldOptions'] = $this->getFieldOptions(); + $this->vars['selectedValues'] = $this->getLoadValue(); + $this->vars['customSeparators'] = $this->getCustomSeparators(); + } + + /** + * @inheritDoc + */ + public function getSaveValue($value) + { + if (!is_array($value)) { + $value = [$value]; + } + + $value = array_values(array_filter($value)); + + if ($this->mode === static::MODE_RELATION) { + return $this->hydrateRelationSaveValue($value); + } + + if ($this->mode === static::MODE_STRING) { + return implode($this->getSeparatorCharacter(), $value); + } + + return $value; + } + + /** + * Returns an array suitable for saving against a relation (array of keys). + * This method also creates non-existent tags. + */ + protected function hydrateRelationSaveValue(array $names): ?array + { + $relation = $this->getRelationObject(); + $relationModel = $this->getRelationModel(); + + $keyName = $relationModel->getKeyName(); + $pivot = in_array(get_class($relation), [BelongsToMany::class, MorphToMany::class]); + + if ($pivot) { + $existingTags = $relationModel->whereIn($this->nameFrom, $names)->lists($this->nameFrom, $keyName); + } else { + $existingTags = $relation->lists($this->nameFrom, $keyName); + } + + $newTags = $this->customTags ? array_diff($names, $existingTags) : []; + $deletedTags = $this->customTags ? array_diff($existingTags, $names) : []; + + foreach ($newTags as $newTag) { + if ($pivot) { + $newModel = new $relationModel; + $newModel->{$this->nameFrom} = $newTag; + $newModel->save(); + } else { + $newModel = $relation->create([$this->nameFrom => $newTag]); + } + $existingTags[$newModel->getKey()] = $newTag; + } + + if (!$pivot && $deletedTags) { + $deletedKeys = array_keys($deletedTags); + $relation->whereIn($keyName, $deletedKeys)->delete(); + foreach ($deletedTags as $id) { + unset($existingTags[$id]); + } + } + + return array_keys($existingTags); + } + + /** + * @inheritDoc + */ + public function getLoadValue() + { + $value = parent::getLoadValue(); + + if ($this->mode === static::MODE_RELATION) { + return $this->getRelationObject()->lists($this->nameFrom); + } + + return $this->mode === static::MODE_STRING + ? explode($this->getSeparatorCharacter(), $value) + : $value; + } + + /** + * Returns defined field options, or from the relation if available. + * @return array + */ + public function getFieldOptions() + { + $options = $this->formField->options(); + + if (!$options && $this->mode === static::MODE_RELATION) { + $options = RelationBase::noConstraints(function () { + $query = $this->getRelationObject()->newQuery(); + + // Even though "no constraints" is applied, belongsToMany constrains the query + // by joining its pivot table. Remove all joins from the query. + $query->getQuery()->getQuery()->joins = []; + + return $query->lists($this->nameFrom); + }); + } + + return $options; + } + + /** + * Returns character(s) to use for separating keywords. + * @return mixed + */ + protected function getCustomSeparators() + { + if (!$this->customTags) { + return false; + } + + $separators = []; + + $separators[] = $this->getSeparatorCharacter(); + + return implode('|', $separators); + } + + /** + * Convert the character word to the singular character. + * @return string + */ + protected function getSeparatorCharacter() + { + switch (strtolower($this->separator)) { + case 'comma': + return ','; + case 'space': + return ' '; + } + } +} diff --git a/modules/backend/formwidgets/codeeditor/README.md b/modules/backend/formwidgets/codeeditor/README.md new file mode 100644 index 0000000..e8989c5 --- /dev/null +++ b/modules/backend/formwidgets/codeeditor/README.md @@ -0,0 +1,586 @@ +# Monaco Code Editor for Winter CMS + +This is the Monaco Editor integration for Winter CMS Backend, replacing the legacy Ace Editor with Microsoft's Monaco Editor (the same editor that powers VS Code). + +## Overview + +**Monaco Editor** provides a rich, modern code editing experience with: +- IntelliSense (code completion) +- Syntax highlighting for 15+ languages +- Advanced find/replace with regex support +- Multi-cursor editing +- Code folding +- Bracket matching and colorization +- Minimap overview +- Color picker for CSS colors +- And many more VS Code features + +## Features + +### Supported Languages (15) + +1. **TypeScript** - Full TypeScript support with type checking +2. **JavaScript** - Modern ES6+ support +3. **CSS** - Including CSS3 properties +4. **JSON** - With schema validation +5. **HTML** - HTML5 support +6. **INI** - Configuration files +7. **LESS** - CSS preprocessor +8. **Markdown** - Rich markdown editing +9. **MySQL** - SQL syntax highlighting +10. **PHP** - Full PHP support +11. **SCSS** - Sass CSS preprocessor +12. **Twig** - Template engine syntax +13. **XML** - Markup language support +14. **YAML** - Configuration file support + +### Monaco Features (20+) + +Enabled features include: +- Anchor select +- Bracket matching +- Caret operations +- Clipboard operations +- Code lens +- Color picker +- Comment toggling +- Context menu +- Cursor undo/redo +- Find and replace +- Code folding +- Go to symbol +- Hover information +- In-place replace +- Indentation +- Inline hints +- Links +- Multi-cursor editing +- Parameter hints +- Rename symbol +- Smart select +- Snippets +- Suggest (autocomplete) +- Word highlighter +- Word operations + +### Themes (35+) + +Includes legacy tmTheme themes plus modern JSON themes + +### User Preferences + +All editor preferences are configurable from **Backend → Preferences → Code editor**: + +**Appearance:** +- Font size (default: 12px) +- Theme selection +- Show/hide line numbers (gutter) +- Show/hide invisibles (whitespace) +- Highlight active line +- Show minimap +- Bracket colorization +- Color picker for CSS + +**Behavior:** +- Tab size (default: 4 spaces) +- Use soft tabs (spaces) vs hard tabs +- Word wrap +- Auto-closing brackets/quotes +- Code folding +- Indent guides +- Print margin + +All preferences persist across sessions and are stored per-user. + +## Editor Architecture + +Winter CMS uses a **dual-editor architecture** to optimize for different use cases: + +### Monaco Editor (this FormWidget) +**Used by:** CodeEditor FormWidget +**Location:** `/modules/backend/formwidgets/codeeditor/` +**Purpose:** Advanced code editing with IntelliSense, syntax highlighting, and modern IDE features +**Bundle Size:** ~15 MB gzipped (main bundle + workers) +**Best for:** Writing PHP, JavaScript, CSS, YAML, and other code files + +### Ace Editor (preserved) +**Used by:** RichEditor and MarkdownEditor FormWidgets +**Location:** `/modules/backend/assets/vendor/ace-codeeditor/` +**Purpose:** HTML source code editing within WYSIWYG editors +**Bundle Size:** ~500 KB (significantly lighter) +**Best for:** Viewing/editing raw HTML in rich text contexts + +### Why Both? + +**Monaco for CodeEditor:** +- Full IntelliSense and code completion +- Advanced refactoring tools +- Multi-cursor editing +- Rich language support +- Worth the bundle size for dedicated code editing + +**Ace for RichEditor/MarkdownEditor:** +- Users rarely need advanced IDE features for HTML source view +- Lighter bundle improves page load performance +- Sufficient for basic HTML editing needs +- Reduces total application bundle by keeping WYSIWYG tools lean + +This architecture balances modern features where they matter most (code editing) with performance optimization for general-purpose rich text editing. + +## Technical Details + +### Architecture + +```text +modules/backend/formwidgets/codeeditor/ +├── assets/ +│ ├── css/ +│ │ └── codeeditor.css - Compiled styles +│ ├── fonts/ +│ │ └── codicon.ttf - Monaco icons font +│ ├── js/ +│ │ ├── codeeditor.js - Main Monaco integration +│ │ └── build/ +│ │ ├── codeeditor.bundle.js - Main bundle (19 MB) +│ │ ├── css.worker.js - CSS language worker +│ │ ├── editor.worker.js - Base editor worker +│ │ ├── html.worker.js - HTML language worker +│ │ ├── json.worker.js - JSON language worker +│ │ ├── ts.worker.js - TypeScript worker +│ │ └── [language-chunks] - 15 language modules +│ ├── less/ +│ │ └── codeeditor.less - Source styles +│ ├── themes/ +│ │ ├── [34 .tmTheme files] - Legacy TextMate themes +│ │ ├── one-dark-pro.json - Modern JSON theme +│ │ └── winter.json - Modern JSON theme +│ ├── winter.mix.js - Laravel Mix build configuration +│ └── package.json - NPM dependencies (in parent) +├── partials/ +│ └── codeeditor.htm - Widget template +└── CodeEditor.php - FormWidget class +``` + +### Build System + +**Current:** Laravel Mix 6 with Webpack 5 + +#### Build Command +```bash +php artisan mix:compile --package=module-backend.formwidgets.codeeditor -f +``` + +#### Build Configuration + +See `assets/winter.mix.js`: +- Uses `monaco-editor-webpack-plugin` for proper worker splitting +- Polyfills for browser compatibility (> 0.5%, last 2 versions, Firefox ESR) +- Removes inline codicon font CSS (post-build hook) +- Minification and terser optimization + +### Web Workers + +Monaco Editor uses Web Workers for language services: + +| Worker | Size | Purpose | +|--------|------|---------| +| editor.worker.js | 1.6 MB | Base editor operations | +| ts.worker.js | 22 MB | TypeScript/JavaScript IntelliSense | +| css.worker.js | 4.7 MB | CSS validation and completion | +| html.worker.js | 3.3 MB | HTML validation | +| json.worker.js | 2.2 MB | JSON schema validation | + +Workers are loaded asynchronously and run in separate threads for better performance. + +### Theme System + +Themes are loaded directly as static assets via HTTP fetch (no PHP handler required). Theme preference values include the file extension (e.g., `twilight.tmTheme`, `one-dark-pro.json`). + +#### Supported Formats + +**1. TextMate Themes (.tmTheme)** +Legacy XML-based themes. Converted to Monaco format at runtime using `fast-plist` library. + +**2. JSON Themes (.json)** +Modern VS Code theme format. Parsed and mapped to Monaco's theme structure. + +```javascript +// codeeditor.js - Themes loaded via static fetch +async fetchTheme(themeName) { + // Theme name includes extension (e.g., "twilight.tmTheme", "one-dark-pro.json") + // Legacy values without extension default to .tmTheme + const basePath = window.Snowboard.url().asset('/modules/backend/formwidgets/codeeditor/assets/themes/'); + const response = await fetch(`${basePath}${themeName}`); + // Format determined from file extension +} +``` + +## Usage + +### Basic Usage + +```yaml +# fields.yaml +code: + type: codeeditor + size: giant + language: php +``` + +### Available Options + +```yaml +code: + type: codeeditor + # Editor size + size: tiny|small|large|huge|giant # Default: large + + # Programming language + language: php|javascript|css|html|twig|yaml|etc # Default: php + + # Theme (overrides user preference) + theme: twilight|monokai|github|one-dark-pro|etc + + # Line numbers + showGutter: true|false # Default: true + + # Word wrapping + wordWrap: true|false # Default: true + + # Code folding + codeFolding: true|false # Default: true + + # Auto-closing brackets + autoClosing: true|false # Default: true + + # Soft tabs (spaces) + useSoftTabs: true|false # Default: true + tabSize: 2|4|8 # Default: 4 + + # Font size (px) + fontSize: 10|12|14|16|18 # Default: 12 + + # Read-only mode + readOnly: true|false # Default: false + disabled: true|false # Sets readOnly + + # Display options + showInvisibles: true|false # Default: false + highlightActiveLine: true|false # Default: true + displayIndentGuides: true|false # Default: true + showPrintMargin: true|false # Default: false + showMinimap: true|false # Default: true + bracketColors: true|false # Default: false + showColors: true|false # Default: true (CSS color picker) +``` + +### JavaScript API + +```javascript +// Get editor instance +const $editor = $('#my-editor'); +const wrapper = $editor.data('oc.codeeditor'); + +// Access Monaco instance directly +const monacoEditor = wrapper.editor; + +// Get/set content (via wrapper) +const code = wrapper.getValue(); +wrapper.setValue('function test() {}'); + +// Get/set language +wrapper.setLanguage('javascript'); + +// Change theme +wrapper.setTheme('one-dark-pro'); + +// Insert at cursor +wrapper.insert('code here'); + +// Get cursor position +const position = wrapper.getPosition(); // { lineNumber: 1, column: 1 } + +// Fullscreen +wrapper.enterFullscreen(); +wrapper.exitFullscreen(); +``` + +### Migrating from ACE to Monaco API + +Winter CMS has migrated from ACE Editor to Monaco Editor. While backward compatibility is maintained for accessing the editor instance via jQuery `.data('oc.codeEditor')`, direct ACE API calls need to be updated. + +#### Breaking Changes + +**ACE's Session API is Removed:** +- `editor.getSession()` → No longer available +- ACE used a separate "session" object for document operations +- Monaco combines session and model into a single API + +**Position Indexing Changed:** +- ACE uses **0-indexed** positions (rows and columns start at 0) +- Monaco uses **1-indexed** positions (lines and columns start at 1) +- Example: ACE row 5 = Monaco line 6, ACE column 0 = Monaco column 1 + +**Annotations Replaced with Markers:** +- ACE's `setAnnotations()` → Monaco's `monaco.editor.setModelMarkers()` +- Different data structure and API + +#### Quick Migration Guide + +**Getting/Setting Editor Value:** + +```javascript +// ❌ OLD (ACE API - Deprecated) +const editor = $('[data-control=codeeditor]').data('oc.codeEditor').editor; +const value = editor.getSession().getValue(); +editor.getSession().setValue('new value'); + +// ✅ NEW (Recommended - Use Wrapper) +const wrapper = $('[data-control=codeeditor]').data('oc.codeEditor'); +const value = wrapper.getValue(); +wrapper.setValue('new value'); + +// ✅ ALTERNATIVE (Direct Monaco API) +const monacoEditor = wrapper.editor; +const value = monacoEditor.getModel().getValue(); +monacoEditor.getModel().setValue('new value'); +``` + +**Inserting Text at Cursor:** + +```javascript +// ❌ OLD (ACE API) +editor.insert('text'); + +// ✅ NEW (Wrapper provides this method) +wrapper.insert('text'); +``` + +**Working with Annotations/Markers:** + +```javascript +// ❌ OLD (ACE Annotations) +editor.getSession().setAnnotations([ + { row: 5, column: 0, text: 'Warning message', type: 'warning' } +]); + +// Clear annotations +editor.getSession().setAnnotations([]); + +// ✅ NEW (Monaco Wrapper Method - Recommended) +wrapper.setMarkers('sourceId', [ + { + startLineNumber: 6, // ACE row 5 = Monaco line 6 (1-indexed!) + startColumn: 1, // ACE column 0 = Monaco column 1 + endLineNumber: 6, + endColumn: Number.MAX_VALUE, // End of line + message: 'Warning message', + severity: wrapper.monaco.MarkerSeverity.Warning // Info, Warning, or Error + } +]); + +// Clear markers +wrapper.setMarkers('sourceId', []); +``` + +**Getting Cursor Position:** + +```javascript +// ❌ OLD (ACE API) +const cursor = editor.getCursorPosition(); // { row: 5, column: 10 } (0-indexed) + +// ✅ NEW (Wrapper) +const position = wrapper.getPosition(); // { lineNumber: 6, column: 11 } (1-indexed) + +// ✅ ALTERNATIVE (Direct Monaco) +const position = wrapper.editor.getPosition(); +``` + +**Getting Selection:** + +```javascript +// ❌ OLD (ACE API) +const range = editor.getSelection().getRange(); + +// ✅ NEW (Wrapper) +const selection = wrapper.getSelection(); + +// ✅ ALTERNATIVE (Direct Monaco) +const selection = wrapper.editor.getSelection(); +``` + +#### API Comparison Table + +| Operation | ACE API (Deprecated) | Monaco Wrapper (Recommended) | Direct Monaco API | +|-----------|---------------------|------------------------------|-------------------| +| Get value | `editor.getSession().getValue()` | `wrapper.getValue()` | `editor.getModel().getValue()` | +| Set value | `editor.getSession().setValue(v)` | `wrapper.setValue(v)` | `editor.getModel().setValue(v)` | +| Insert text | `editor.insert(text)` | `wrapper.insert(text)` | Complex - use wrapper | +| Get position | `editor.getCursorPosition()` | `wrapper.getPosition()` | `editor.getPosition()` | +| Get selection | `editor.getSelection()` | `wrapper.getSelection()` | `editor.getSelection()` | +| Set annotations | `editor.getSession().setAnnotations()` | `wrapper.setMarkers(id, markers)` | `monaco.editor.setModelMarkers()` | +| Focus editor | `editor.focus()` | `wrapper.focus()` | `editor.focus()` | +| Set language | N/A | `wrapper.setLanguage(lang)` | Complex - use wrapper | + +#### Migration Checklist for Plugin Developers + +If your plugin interacts with the CodeEditor widget, follow these steps: + +1. **Update Editor Instance Access:** + - ✅ Keep: `.data('oc.codeEditor')` - Returns the wrapper + - ⚠️ Avoid: `.data('oc.codeEditor').editor` - Returns raw Monaco (advanced use only) + +2. **Replace ACE Session Methods:** + - ❌ Remove all: `getSession().getValue()` → ✅ Use: `getValue()` + - ❌ Remove all: `getSession().setValue()` → ✅ Use: `setValue()` + +3. **Update Annotations:** + - ❌ Remove: `getSession().setAnnotations(annotations)` + - ✅ Add: `wrapper.setMarkers(sourceId, markers)` + - ⚠️ Remember: Convert 0-indexed row/column to 1-indexed line/column + - Use `wrapper.monaco.MarkerSeverity` for severity constants + +4. **Test Thoroughly:** + - Verify all editor interactions work + - Check that cursor operations use correct indexing + - Ensure markers/warnings display correctly + +#### Available Wrapper Methods + +The Monaco Snowboard editor wrapper provides these convenience methods: + +```javascript +const wrapper = $('[data-control=codeeditor]').data('oc.codeEditor'); + +// Content +wrapper.getValue() // Get editor content +wrapper.setValue(value) // Set editor content +wrapper.insert(text) // Insert at cursor position + +// Position & Selection +wrapper.getPosition() // Get cursor position (1-indexed) +wrapper.getSelection() // Get selection range + +// Markers (Errors/Warnings/Info with squiggly underlines) +wrapper.setMarkers(sourceId, markers) // Set error/warning markers in editor +// Example: wrapper.setMarkers('myPlugin', [{ startLineNumber: 5, startColumn: 1, +// endLineNumber: 5, endColumn: Number.MAX_VALUE, message: 'Warning', +// severity: wrapper.monaco.MarkerSeverity.Warning }]) + +// Decorations (Visual highlights WITHOUT error semantics) +wrapper.setDecorations(sourceId, decorations) // Set visual highlights (no squiggles) +// Example: wrapper.setDecorations('myHighlight', [{ range: new monaco.Range(5, 1, 5, Number.MAX_VALUE), +// options: { isWholeLine: true, className: 'myHighlightClass', +// linesDecorationsClassName: 'myGutterClass' } }]) + +// Configuration +wrapper.setLanguage(lang) // Change syntax highlighting language +wrapper.setTheme(theme) // Change color theme +wrapper.focus() // Focus the editor + +// View +wrapper.enterFullscreen() // Enter fullscreen mode +wrapper.exitFullscreen() // Exit fullscreen mode +wrapper.refresh() // Refresh editor (re-create instance) + +// Direct Access (Advanced) +wrapper.editor // Access Monaco editor instance +wrapper.getEditor() // Same as wrapper.editor +wrapper.getModel() // Get Monaco model +wrapper.monaco // Access Monaco namespace (for constants like MarkerSeverity) +``` + +#### Example: Winter.Builder Plugin Migration + +The Winter.Builder plugin was migrated to use Monaco API. Here's a real example: + +**Before (ACE):** +```javascript +Localization.prototype.copyStringsFromDone = function(data) { + var codeEditor = this.getCodeEditor($masterTabPane); + + // Set value using ACE Session API + codeEditor.getSession().setValue(responseData.strings); + + // Set annotations using ACE + var annotations = []; + for (var i = 0; i < updatedLines.length; i++) { + annotations.push({ + row: updatedLines[i], // 0-indexed + column: 0, + text: 'New String', + type: 'warning' + }); + } + codeEditor.getSession().setAnnotations(annotations); +} +``` + +**After (Monaco):** +```javascript +Localization.prototype.copyStringsFromDone = function(data) { + var wrapper = this.getCodeEditor($masterTabPane); + + // Set value using wrapper method + wrapper.setValue(responseData.strings); + + // Convert to Monaco decorations (visual highlights without error semantics) + var decorations = []; + for (var i = 0; i < updatedLines.length; i++) { + decorations.push({ + range: new wrapper.monaco.Range( + updatedLines[i] + 1, // Convert to 1-indexed! + 1, // Start column + updatedLines[i] + 1, // End line (same line) + Number.MAX_VALUE // End column (end of line) + ), + options: { + isWholeLine: true, + className: 'builder-new-translation-line', // Background highlight + linesDecorationsClassName: 'builder-new-translation-gutter', // Gutter indicator + hoverMessage: { value: 'New string or section' } // Tooltip on hover + } + }); + } + wrapper.setDecorations('builderLocalization', decorations); +} +``` + +## Testing + +### Playwright E2E Tests + +Comprehensive test suite with 55+ tests: + +```bash +# Run all tests +npm run test:e2e + +# Run with UI +npm run test:e2e:ui + +# Run specific test file +npx playwright test fullscreen.spec.js + +# Debug tests +npm run test:e2e:debug +``` + +### Test Coverage + +- **Fullscreen functionality** (6 tests) +- **Theme loading and switching** (9 tests) +- **Language support** (14 tests for all 15 languages) +- **Monaco features** (14 tests: find, replace, folding, multi-cursor, etc.) +- **Preferences persistence** (12 tests) + +See `tests/e2e/README-TESTING.md` for full testing documentation. + +## Resources + +- **Monaco Editor Documentation:** https://microsoft.github.io/monaco-editor/ +- **Monaco Editor GitHub:** https://github.com/microsoft/monaco-editor +- **VS Code Themes:** https://marketplace.visualstudio.com/search?target=VSCode&category=Themes +- **Winter CMS Docs:** https://wintercms.com/docs +- **PR #801:** https://github.com/wintercms/winter/pull/801 +- **Issue #431:** https://github.com/wintercms/winter/issues/431 diff --git a/modules/backend/formwidgets/codeeditor/assets/css/codeeditor.css b/modules/backend/formwidgets/codeeditor/assets/css/codeeditor.css new file mode 100644 index 0000000..20a9699 --- /dev/null +++ b/modules/backend/formwidgets/codeeditor/assets/css/codeeditor.css @@ -0,0 +1 @@ +.field-codeeditor{border:2px solid #d1d6d9;border-radius:3px;display:flex;flex-direction:column;position:relative;width:100%}.field-codeeditor.editor-focus{border:2px solid #d1d6d9}.field-codeeditor .editor-code{border-radius:3px}.field-codeeditor.size-tiny{height:50px}.field-codeeditor.size-small{height:100px}.field-codeeditor.size-large{height:200px}.field-codeeditor.size-huge{height:250px}.field-codeeditor.size-giant{height:350px}.field-codeeditor .editor-container{flex-grow:1;flex-shrink:1;height:100%;width:100%}.field-codeeditor .editor-toolbar{align-items:center;background:rgba(0,0,0,.8);display:flex;flex-direction:row;flex-grow:0;flex-shrink:0;font-size:11px;gap:20px;height:24px;padding:2px 8px;position:relative;z-index:10}.field-codeeditor .editor-toolbar:before{background:rgba(0,0,0,.08);content:"";height:100%;left:0;position:absolute;top:0;width:100%;z-index:9}.field-codeeditor .editor-toolbar.is-dark:before{background:hsla(0,0%,100%,.08)}.field-codeeditor .editor-toolbar>div{z-index:11}.field-codeeditor .editor-toolbar .position{flex-grow:1}.field-codeeditor .editor-toolbar .actions .action{color:inherit;font-size:1.1rem;margin:-2px 0;opacity:.4;padding:0 5px}.field-codeeditor .editor-toolbar .actions .action:hover{opacity:.8}.field-codeeditor .editor-toolbar .actions .action.active{opacity:1}@font-face{font-display:block;font-family:codicon;src:url(../fonts/codicon.ttf?9d44d5a6cc2c9ad0152755e704fa37ba) format("truetype")}.codicon[class*=codicon-]{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font:normal normal normal 16px/1 codicon;text-align:center;text-decoration:none;text-rendering:auto;-moz-user-select:none;user-select:none;-webkit-user-select:none;-ms-user-select:none}@keyframes codicon-spin{to{transform:rotate(1turn)}}.codicon-gear.codicon-modifier-spin,.codicon-loading.codicon-modifier-spin,.codicon-sync.codicon-modifier-spin{animation:codicon-spin 1.5s steps(30) infinite}.codicon-modifier-disabled{opacity:.5}.codicon-modifier-hidden{opacity:0}.codicon-loading{animation-duration:1s!important;animation-timing-function:cubic-bezier(.53,.21,.29,.67)!important}.codicon-add:before,.codicon-gist-new:before,.codicon-plus:before,.codicon-repo-create:before{content:"\ea60"}.codicon-light-bulb:before,.codicon-lightbulb:before{content:"\ea61"}.codicon-repo-delete:before,.codicon-repo:before{content:"\ea62"}.codicon-gist-fork:before,.codicon-repo-forked:before{content:"\ea63"}.codicon-git-pull-request-abandoned:before,.codicon-git-pull-request:before{content:"\ea64"}.codicon-keyboard:before,.codicon-record-keys:before{content:"\ea65"}.codicon-tag-add:before,.codicon-tag-remove:before,.codicon-tag:before{content:"\ea66"}.codicon-person-filled:before,.codicon-person-follow:before,.codicon-person-outline:before,.codicon-person:before{content:"\ea67"}.codicon-git-branch-create:before,.codicon-git-branch-delete:before,.codicon-git-branch:before,.codicon-source-control:before{content:"\ea68"}.codicon-mirror-public:before,.codicon-mirror:before{content:"\ea69"}.codicon-star-add:before,.codicon-star-delete:before,.codicon-star-empty:before,.codicon-star:before{content:"\ea6a"}.codicon-comment-add:before,.codicon-comment:before{content:"\ea6b"}.codicon-alert:before,.codicon-warning:before{content:"\ea6c"}.codicon-search-save:before,.codicon-search:before{content:"\ea6d"}.codicon-log-out:before,.codicon-sign-out:before{content:"\ea6e"}.codicon-log-in:before,.codicon-sign-in:before{content:"\ea6f"}.codicon-eye-unwatch:before,.codicon-eye-watch:before,.codicon-eye:before{content:"\ea70"}.codicon-circle-filled:before,.codicon-close-dirty:before,.codicon-debug-breakpoint-disabled:before,.codicon-debug-breakpoint:before,.codicon-debug-hint:before,.codicon-primitive-dot:before,.codicon-terminal-decoration-success:before{content:"\ea71"}.codicon-primitive-square:before{content:"\ea72"}.codicon-edit:before,.codicon-pencil:before{content:"\ea73"}.codicon-info:before,.codicon-issue-opened:before{content:"\ea74"}.codicon-gist-private:before,.codicon-git-fork-private:before,.codicon-lock:before,.codicon-mirror-private:before{content:"\ea75"}.codicon-close:before,.codicon-remove-close:before,.codicon-x:before{content:"\ea76"}.codicon-repo-sync:before,.codicon-sync:before{content:"\ea77"}.codicon-clone:before,.codicon-desktop-download:before{content:"\ea78"}.codicon-beaker:before,.codicon-microscope:before{content:"\ea79"}.codicon-device-desktop:before,.codicon-vm:before{content:"\ea7a"}.codicon-file-text:before,.codicon-file:before{content:"\ea7b"}.codicon-ellipsis:before,.codicon-kebab-horizontal:before,.codicon-more:before{content:"\ea7c"}.codicon-mail-reply:before,.codicon-reply:before{content:"\ea7d"}.codicon-organization-filled:before,.codicon-organization-outline:before,.codicon-organization:before{content:"\ea7e"}.codicon-file-add:before,.codicon-new-file:before{content:"\ea7f"}.codicon-file-directory-create:before,.codicon-new-folder:before{content:"\ea80"}.codicon-trash:before,.codicon-trashcan:before{content:"\ea81"}.codicon-clock:before,.codicon-history:before{content:"\ea82"}.codicon-file-directory:before,.codicon-folder:before,.codicon-symbol-folder:before{content:"\ea83"}.codicon-github:before,.codicon-logo-github:before,.codicon-mark-github:before{content:"\ea84"}.codicon-console:before,.codicon-repl:before,.codicon-terminal:before{content:"\ea85"}.codicon-symbol-event:before,.codicon-zap:before{content:"\ea86"}.codicon-error:before,.codicon-stop:before{content:"\ea87"}.codicon-symbol-variable:before,.codicon-variable:before{content:"\ea88"}.codicon-array:before,.codicon-symbol-array:before{content:"\ea8a"}.codicon-symbol-module:before,.codicon-symbol-namespace:before,.codicon-symbol-object:before,.codicon-symbol-package:before{content:"\ea8b"}.codicon-symbol-constructor:before,.codicon-symbol-function:before,.codicon-symbol-method:before{content:"\ea8c"}.codicon-symbol-boolean:before,.codicon-symbol-null:before{content:"\ea8f"}.codicon-symbol-number:before,.codicon-symbol-numeric:before{content:"\ea90"}.codicon-symbol-struct:before,.codicon-symbol-structure:before{content:"\ea91"}.codicon-symbol-parameter:before,.codicon-symbol-type-parameter:before{content:"\ea92"}.codicon-symbol-key:before,.codicon-symbol-text:before{content:"\ea93"}.codicon-go-to-file:before,.codicon-symbol-reference:before{content:"\ea94"}.codicon-symbol-enum:before,.codicon-symbol-value:before{content:"\ea95"}.codicon-symbol-ruler:before,.codicon-symbol-unit:before{content:"\ea96"}.codicon-activate-breakpoints:before{content:"\ea97"}.codicon-archive:before{content:"\ea98"}.codicon-arrow-both:before{content:"\ea99"}.codicon-arrow-down:before{content:"\ea9a"}.codicon-arrow-left:before{content:"\ea9b"}.codicon-arrow-right:before{content:"\ea9c"}.codicon-arrow-small-down:before{content:"\ea9d"}.codicon-arrow-small-left:before{content:"\ea9e"}.codicon-arrow-small-right:before{content:"\ea9f"}.codicon-arrow-small-up:before{content:"\eaa0"}.codicon-arrow-up:before{content:"\eaa1"}.codicon-bell:before{content:"\eaa2"}.codicon-bold:before{content:"\eaa3"}.codicon-book:before{content:"\eaa4"}.codicon-bookmark:before{content:"\eaa5"}.codicon-debug-breakpoint-conditional-unverified:before{content:"\eaa6"}.codicon-debug-breakpoint-conditional-disabled:before,.codicon-debug-breakpoint-conditional:before{content:"\eaa7"}.codicon-debug-breakpoint-data-unverified:before{content:"\eaa8"}.codicon-debug-breakpoint-data-disabled:before,.codicon-debug-breakpoint-data:before{content:"\eaa9"}.codicon-debug-breakpoint-log-unverified:before{content:"\eaaa"}.codicon-debug-breakpoint-log-disabled:before,.codicon-debug-breakpoint-log:before{content:"\eaab"}.codicon-briefcase:before{content:"\eaac"}.codicon-broadcast:before{content:"\eaad"}.codicon-browser:before{content:"\eaae"}.codicon-bug:before{content:"\eaaf"}.codicon-calendar:before{content:"\eab0"}.codicon-case-sensitive:before{content:"\eab1"}.codicon-check:before{content:"\eab2"}.codicon-checklist:before{content:"\eab3"}.codicon-chevron-down:before{content:"\eab4"}.codicon-chevron-left:before{content:"\eab5"}.codicon-chevron-right:before{content:"\eab6"}.codicon-chevron-up:before{content:"\eab7"}.codicon-chrome-close:before{content:"\eab8"}.codicon-chrome-maximize:before{content:"\eab9"}.codicon-chrome-minimize:before{content:"\eaba"}.codicon-chrome-restore:before{content:"\eabb"}.codicon-circle-outline:before,.codicon-circle:before,.codicon-debug-breakpoint-unverified:before,.codicon-terminal-decoration-incomplete:before{content:"\eabc"}.codicon-circle-slash:before{content:"\eabd"}.codicon-circuit-board:before{content:"\eabe"}.codicon-clear-all:before{content:"\eabf"}.codicon-clippy:before{content:"\eac0"}.codicon-close-all:before{content:"\eac1"}.codicon-cloud-download:before{content:"\eac2"}.codicon-cloud-upload:before{content:"\eac3"}.codicon-code:before{content:"\eac4"}.codicon-collapse-all:before{content:"\eac5"}.codicon-color-mode:before{content:"\eac6"}.codicon-comment-discussion:before{content:"\eac7"}.codicon-credit-card:before{content:"\eac9"}.codicon-dash:before{content:"\eacc"}.codicon-dashboard:before{content:"\eacd"}.codicon-database:before{content:"\eace"}.codicon-debug-continue:before{content:"\eacf"}.codicon-debug-disconnect:before{content:"\ead0"}.codicon-debug-pause:before{content:"\ead1"}.codicon-debug-restart:before{content:"\ead2"}.codicon-debug-start:before{content:"\ead3"}.codicon-debug-step-into:before{content:"\ead4"}.codicon-debug-step-out:before{content:"\ead5"}.codicon-debug-step-over:before{content:"\ead6"}.codicon-debug-stop:before{content:"\ead7"}.codicon-debug:before{content:"\ead8"}.codicon-device-camera-video:before{content:"\ead9"}.codicon-device-camera:before{content:"\eada"}.codicon-device-mobile:before{content:"\eadb"}.codicon-diff-added:before{content:"\eadc"}.codicon-diff-ignored:before{content:"\eadd"}.codicon-diff-modified:before{content:"\eade"}.codicon-diff-removed:before{content:"\eadf"}.codicon-diff-renamed:before{content:"\eae0"}.codicon-diff:before{content:"\eae1"}.codicon-discard:before{content:"\eae2"}.codicon-editor-layout:before{content:"\eae3"}.codicon-empty-window:before{content:"\eae4"}.codicon-exclude:before{content:"\eae5"}.codicon-extensions:before{content:"\eae6"}.codicon-eye-closed:before{content:"\eae7"}.codicon-file-binary:before{content:"\eae8"}.codicon-file-code:before{content:"\eae9"}.codicon-file-media:before{content:"\eaea"}.codicon-file-pdf:before{content:"\eaeb"}.codicon-file-submodule:before{content:"\eaec"}.codicon-file-symlink-directory:before{content:"\eaed"}.codicon-file-symlink-file:before{content:"\eaee"}.codicon-file-zip:before{content:"\eaef"}.codicon-files:before{content:"\eaf0"}.codicon-filter:before{content:"\eaf1"}.codicon-flame:before{content:"\eaf2"}.codicon-fold-down:before{content:"\eaf3"}.codicon-fold-up:before{content:"\eaf4"}.codicon-fold:before{content:"\eaf5"}.codicon-folder-active:before{content:"\eaf6"}.codicon-folder-opened:before{content:"\eaf7"}.codicon-gear:before{content:"\eaf8"}.codicon-gift:before{content:"\eaf9"}.codicon-gist-secret:before{content:"\eafa"}.codicon-gist:before{content:"\eafb"}.codicon-git-commit:before{content:"\eafc"}.codicon-compare-changes:before,.codicon-git-compare:before{content:"\eafd"}.codicon-git-merge:before{content:"\eafe"}.codicon-github-action:before{content:"\eaff"}.codicon-github-alt:before{content:"\eb00"}.codicon-globe:before{content:"\eb01"}.codicon-grabber:before{content:"\eb02"}.codicon-graph:before{content:"\eb03"}.codicon-gripper:before{content:"\eb04"}.codicon-heart:before{content:"\eb05"}.codicon-home:before{content:"\eb06"}.codicon-horizontal-rule:before{content:"\eb07"}.codicon-hubot:before{content:"\eb08"}.codicon-inbox:before{content:"\eb09"}.codicon-issue-reopened:before{content:"\eb0b"}.codicon-issues:before{content:"\eb0c"}.codicon-italic:before{content:"\eb0d"}.codicon-jersey:before{content:"\eb0e"}.codicon-json:before{content:"\eb0f"}.codicon-kebab-vertical:before{content:"\eb10"}.codicon-key:before{content:"\eb11"}.codicon-law:before{content:"\eb12"}.codicon-lightbulb-autofix:before{content:"\eb13"}.codicon-link-external:before{content:"\eb14"}.codicon-link:before{content:"\eb15"}.codicon-list-ordered:before{content:"\eb16"}.codicon-list-unordered:before{content:"\eb17"}.codicon-live-share:before{content:"\eb18"}.codicon-loading:before{content:"\eb19"}.codicon-location:before{content:"\eb1a"}.codicon-mail-read:before{content:"\eb1b"}.codicon-mail:before{content:"\eb1c"}.codicon-markdown:before{content:"\eb1d"}.codicon-megaphone:before{content:"\eb1e"}.codicon-mention:before{content:"\eb1f"}.codicon-milestone:before{content:"\eb20"}.codicon-mortar-board:before{content:"\eb21"}.codicon-move:before{content:"\eb22"}.codicon-multiple-windows:before{content:"\eb23"}.codicon-mute:before{content:"\eb24"}.codicon-no-newline:before{content:"\eb25"}.codicon-note:before{content:"\eb26"}.codicon-octoface:before{content:"\eb27"}.codicon-open-preview:before{content:"\eb28"}.codicon-package:before{content:"\eb29"}.codicon-paintcan:before{content:"\eb2a"}.codicon-pin:before{content:"\eb2b"}.codicon-play:before,.codicon-run:before{content:"\eb2c"}.codicon-plug:before{content:"\eb2d"}.codicon-preserve-case:before{content:"\eb2e"}.codicon-preview:before{content:"\eb2f"}.codicon-project:before{content:"\eb30"}.codicon-pulse:before{content:"\eb31"}.codicon-question:before{content:"\eb32"}.codicon-quote:before{content:"\eb33"}.codicon-radio-tower:before{content:"\eb34"}.codicon-reactions:before{content:"\eb35"}.codicon-references:before{content:"\eb36"}.codicon-refresh:before{content:"\eb37"}.codicon-regex:before{content:"\eb38"}.codicon-remote-explorer:before{content:"\eb39"}.codicon-remote:before{content:"\eb3a"}.codicon-remove:before{content:"\eb3b"}.codicon-replace-all:before{content:"\eb3c"}.codicon-replace:before{content:"\eb3d"}.codicon-repo-clone:before{content:"\eb3e"}.codicon-repo-force-push:before{content:"\eb3f"}.codicon-repo-pull:before{content:"\eb40"}.codicon-repo-push:before{content:"\eb41"}.codicon-report:before{content:"\eb42"}.codicon-request-changes:before{content:"\eb43"}.codicon-rocket:before{content:"\eb44"}.codicon-root-folder-opened:before{content:"\eb45"}.codicon-root-folder:before{content:"\eb46"}.codicon-rss:before{content:"\eb47"}.codicon-ruby:before{content:"\eb48"}.codicon-save-all:before{content:"\eb49"}.codicon-save-as:before{content:"\eb4a"}.codicon-save:before{content:"\eb4b"}.codicon-screen-full:before{content:"\eb4c"}.codicon-screen-normal:before{content:"\eb4d"}.codicon-search-stop:before{content:"\eb4e"}.codicon-server:before{content:"\eb50"}.codicon-settings-gear:before{content:"\eb51"}.codicon-settings:before{content:"\eb52"}.codicon-shield:before{content:"\eb53"}.codicon-smiley:before{content:"\eb54"}.codicon-sort-precedence:before{content:"\eb55"}.codicon-split-horizontal:before{content:"\eb56"}.codicon-split-vertical:before{content:"\eb57"}.codicon-squirrel:before{content:"\eb58"}.codicon-star-full:before{content:"\eb59"}.codicon-star-half:before{content:"\eb5a"}.codicon-symbol-class:before{content:"\eb5b"}.codicon-symbol-color:before{content:"\eb5c"}.codicon-symbol-constant:before{content:"\eb5d"}.codicon-symbol-enum-member:before{content:"\eb5e"}.codicon-symbol-field:before{content:"\eb5f"}.codicon-symbol-file:before{content:"\eb60"}.codicon-symbol-interface:before{content:"\eb61"}.codicon-symbol-keyword:before{content:"\eb62"}.codicon-symbol-misc:before{content:"\eb63"}.codicon-symbol-operator:before{content:"\eb64"}.codicon-symbol-property:before,.codicon-wrench-subaction:before,.codicon-wrench:before{content:"\eb65"}.codicon-symbol-snippet:before{content:"\eb66"}.codicon-tasklist:before{content:"\eb67"}.codicon-telescope:before{content:"\eb68"}.codicon-text-size:before{content:"\eb69"}.codicon-three-bars:before{content:"\eb6a"}.codicon-thumbsdown:before{content:"\eb6b"}.codicon-thumbsup:before{content:"\eb6c"}.codicon-tools:before{content:"\eb6d"}.codicon-triangle-down:before{content:"\eb6e"}.codicon-triangle-left:before{content:"\eb6f"}.codicon-triangle-right:before{content:"\eb70"}.codicon-triangle-up:before{content:"\eb71"}.codicon-twitter:before{content:"\eb72"}.codicon-unfold:before{content:"\eb73"}.codicon-unlock:before{content:"\eb74"}.codicon-unmute:before{content:"\eb75"}.codicon-unverified:before{content:"\eb76"}.codicon-verified:before{content:"\eb77"}.codicon-versions:before{content:"\eb78"}.codicon-vm-active:before{content:"\eb79"}.codicon-vm-outline:before{content:"\eb7a"}.codicon-vm-running:before{content:"\eb7b"}.codicon-watch:before{content:"\eb7c"}.codicon-whitespace:before{content:"\eb7d"}.codicon-whole-word:before{content:"\eb7e"}.codicon-window:before{content:"\eb7f"}.codicon-word-wrap:before{content:"\eb80"}.codicon-zoom-in:before{content:"\eb81"}.codicon-zoom-out:before{content:"\eb82"}.codicon-list-filter:before{content:"\eb83"}.codicon-list-flat:before{content:"\eb84"}.codicon-list-selection:before,.codicon-selection:before{content:"\eb85"}.codicon-list-tree:before{content:"\eb86"}.codicon-debug-breakpoint-function-unverified:before{content:"\eb87"}.codicon-debug-breakpoint-function-disabled:before,.codicon-debug-breakpoint-function:before{content:"\eb88"}.codicon-debug-stackframe-active:before{content:"\eb89"}.codicon-circle-small-filled:before,.codicon-debug-stackframe-dot:before,.codicon-terminal-decoration-mark:before{content:"\eb8a"}.codicon-debug-stackframe-focused:before,.codicon-debug-stackframe:before{content:"\eb8b"}.codicon-debug-breakpoint-unsupported:before{content:"\eb8c"}.codicon-symbol-string:before{content:"\eb8d"}.codicon-debug-reverse-continue:before{content:"\eb8e"}.codicon-debug-step-back:before{content:"\eb8f"}.codicon-debug-restart-frame:before{content:"\eb90"}.codicon-debug-alt:before{content:"\eb91"}.codicon-call-incoming:before{content:"\eb92"}.codicon-call-outgoing:before{content:"\eb93"}.codicon-menu:before{content:"\eb94"}.codicon-expand-all:before{content:"\eb95"}.codicon-feedback:before{content:"\eb96"}.codicon-group-by-ref-type:before{content:"\eb97"}.codicon-ungroup-by-ref-type:before{content:"\eb98"}.codicon-account:before{content:"\eb99"}.codicon-bell-dot:before{content:"\eb9a"}.codicon-debug-console:before{content:"\eb9b"}.codicon-library:before{content:"\eb9c"}.codicon-output:before{content:"\eb9d"}.codicon-run-all:before{content:"\eb9e"}.codicon-sync-ignored:before{content:"\eb9f"}.codicon-pinned:before{content:"\eba0"}.codicon-github-inverted:before{content:"\eba1"}.codicon-server-process:before{content:"\eba2"}.codicon-server-environment:before{content:"\eba3"}.codicon-issue-closed:before,.codicon-pass:before{content:"\eba4"}.codicon-stop-circle:before{content:"\eba5"}.codicon-play-circle:before{content:"\eba6"}.codicon-record:before{content:"\eba7"}.codicon-debug-alt-small:before{content:"\eba8"}.codicon-vm-connect:before{content:"\eba9"}.codicon-cloud:before{content:"\ebaa"}.codicon-merge:before{content:"\ebab"}.codicon-export:before{content:"\ebac"}.codicon-graph-left:before{content:"\ebad"}.codicon-magnet:before{content:"\ebae"}.codicon-notebook:before{content:"\ebaf"}.codicon-redo:before{content:"\ebb0"}.codicon-check-all:before{content:"\ebb1"}.codicon-pinned-dirty:before{content:"\ebb2"}.codicon-pass-filled:before{content:"\ebb3"}.codicon-circle-large-filled:before{content:"\ebb4"}.codicon-circle-large-outline:before,.codicon-circle-large:before{content:"\ebb5"}.codicon-combine:before,.codicon-gather:before{content:"\ebb6"}.codicon-table:before{content:"\ebb7"}.codicon-variable-group:before{content:"\ebb8"}.codicon-type-hierarchy:before{content:"\ebb9"}.codicon-type-hierarchy-sub:before{content:"\ebba"}.codicon-type-hierarchy-super:before{content:"\ebbb"}.codicon-git-pull-request-create:before{content:"\ebbc"}.codicon-run-above:before{content:"\ebbd"}.codicon-run-below:before{content:"\ebbe"}.codicon-notebook-template:before{content:"\ebbf"}.codicon-debug-rerun:before{content:"\ebc0"}.codicon-workspace-trusted:before{content:"\ebc1"}.codicon-workspace-untrusted:before{content:"\ebc2"}.codicon-workspace-unknown:before{content:"\ebc3"}.codicon-terminal-cmd:before{content:"\ebc4"}.codicon-terminal-debian:before{content:"\ebc5"}.codicon-terminal-linux:before{content:"\ebc6"}.codicon-terminal-powershell:before{content:"\ebc7"}.codicon-terminal-tmux:before{content:"\ebc8"}.codicon-terminal-ubuntu:before{content:"\ebc9"}.codicon-terminal-bash:before{content:"\ebca"}.codicon-arrow-swap:before{content:"\ebcb"}.codicon-copy:before{content:"\ebcc"}.codicon-person-add:before{content:"\ebcd"}.codicon-filter-filled:before{content:"\ebce"}.codicon-wand:before{content:"\ebcf"}.codicon-debug-line-by-line:before{content:"\ebd0"}.codicon-inspect:before{content:"\ebd1"}.codicon-layers:before{content:"\ebd2"}.codicon-layers-dot:before{content:"\ebd3"}.codicon-layers-active:before{content:"\ebd4"}.codicon-compass:before{content:"\ebd5"}.codicon-compass-dot:before{content:"\ebd6"}.codicon-compass-active:before{content:"\ebd7"}.codicon-azure:before{content:"\ebd8"}.codicon-issue-draft:before{content:"\ebd9"}.codicon-git-pull-request-closed:before{content:"\ebda"}.codicon-git-pull-request-draft:before{content:"\ebdb"}.codicon-debug-all:before{content:"\ebdc"}.codicon-debug-coverage:before{content:"\ebdd"}.codicon-run-errors:before{content:"\ebde"}.codicon-folder-library:before{content:"\ebdf"}.codicon-debug-continue-small:before{content:"\ebe0"}.codicon-beaker-stop:before{content:"\ebe1"}.codicon-graph-line:before{content:"\ebe2"}.codicon-graph-scatter:before{content:"\ebe3"}.codicon-pie-chart:before{content:"\ebe4"}.codicon-bracket:before{content:"\eb0f"}.codicon-bracket-dot:before{content:"\ebe5"}.codicon-bracket-error:before{content:"\ebe6"}.codicon-lock-small:before{content:"\ebe7"}.codicon-azure-devops:before{content:"\ebe8"}.codicon-verified-filled:before{content:"\ebe9"}.codicon-newline:before{content:"\ebea"}.codicon-layout:before{content:"\ebeb"}.codicon-layout-activitybar-left:before{content:"\ebec"}.codicon-layout-activitybar-right:before{content:"\ebed"}.codicon-layout-panel-left:before{content:"\ebee"}.codicon-layout-panel-center:before{content:"\ebef"}.codicon-layout-panel-justify:before{content:"\ebf0"}.codicon-layout-panel-right:before{content:"\ebf1"}.codicon-layout-panel:before{content:"\ebf2"}.codicon-layout-sidebar-left:before{content:"\ebf3"}.codicon-layout-sidebar-right:before{content:"\ebf4"}.codicon-layout-statusbar:before{content:"\ebf5"}.codicon-layout-menubar:before{content:"\ebf6"}.codicon-layout-centered:before{content:"\ebf7"}.codicon-target:before{content:"\ebf8"}.codicon-indent:before{content:"\ebf9"}.codicon-record-small:before{content:"\ebfa"}.codicon-error-small:before,.codicon-terminal-decoration-error:before{content:"\ebfb"}.codicon-arrow-circle-down:before{content:"\ebfc"}.codicon-arrow-circle-left:before{content:"\ebfd"}.codicon-arrow-circle-right:before{content:"\ebfe"}.codicon-arrow-circle-up:before{content:"\ebff"}.codicon-layout-sidebar-right-off:before{content:"\ec00"}.codicon-layout-panel-off:before{content:"\ec01"}.codicon-layout-sidebar-left-off:before{content:"\ec02"}.codicon-blank:before{content:"\ec03"}.codicon-heart-filled:before{content:"\ec04"}.codicon-map:before{content:"\ec05"}.codicon-map-filled:before{content:"\ec06"}.codicon-circle-small:before{content:"\ec07"}.codicon-bell-slash:before{content:"\ec08"}.codicon-bell-slash-dot:before{content:"\ec09"}.codicon-comment-unresolved:before{content:"\ec0a"}.codicon-git-pull-request-go-to-changes:before{content:"\ec0b"}.codicon-git-pull-request-new-changes:before{content:"\ec0c"}.codicon-search-fuzzy:before{content:"\ec0d"}.codicon-comment-draft:before{content:"\ec0e"} diff --git a/modules/backend/formwidgets/codeeditor/assets/fonts/codicon.ttf b/modules/backend/formwidgets/codeeditor/assets/fonts/codicon.ttf new file mode 100644 index 0000000..6d9ce31 Binary files /dev/null and b/modules/backend/formwidgets/codeeditor/assets/fonts/codicon.ttf differ diff --git a/modules/backend/formwidgets/codeeditor/assets/js/build/codeeditor.bundle.js b/modules/backend/formwidgets/codeeditor/assets/js/build/codeeditor.bundle.js new file mode 100644 index 0000000..91db948 --- /dev/null +++ b/modules/backend/formwidgets/codeeditor/assets/js/build/codeeditor.bundle.js @@ -0,0 +1,142 @@ +!function(){var e,t,i={4010:function(e,t,i){"use strict";var n={initWith:function(e){const t=document.createElement("div"),i=e.editor.create(t),n=i.constructor.name,o=i.getModel().constructor.name;return{isInstanceValid:function(e){return e.constructor.name===n},isModelValid:function(e){return e.constructor.name===o},isRangesValid:function(e){return!!Array.isArray(e)&&e.every(function(e){return"object"==typeof e&&"Object"===e.constructor.name&&(!!e.hasOwnProperty("range")&&(!!Array.isArray(e.range)&&(4===e.range.length&&(!!e.range.every(e=>e>0&&parseInt(e)===e)&&((!e.hasOwnProperty("allowMultiline")||"boolean"==typeof e.allowMultiline)&&((!e.hasOwnProperty("label")||"string"==typeof e.label)&&(!e.hasOwnProperty("validate")||"function"==typeof e.validate)))))))})}}}};const o=function(e,t,i){return"The value for the "+t+" should be of type "+(Array.isArray(e)?e.join(" | "):e)+". "+(i||"")};var s=function(){const e=function(e,t){return"object"!=typeof e||null===e?this.freeze?Object.freeze(e):e:e instanceof Date?this.freeze?Object.freeze(new Date(e)):new Date(e):t.call(this,e)},t=function(t,i){const n=Object.keys(t),o=new Array(n.length);for(let s=0;s=this[i])&&(e-=this[i]),t}.bind(this),{})},t=Object.create(Object.defineProperties({},{withProto:{value:1},freeze:{value:2}}));for(let i=0;i<=3;i++)e.call(t,i);return t}(),o={withProto:i.bind(n[1]),andFreeze:i.bind(n[2]),withProtoAndFreeze:i.bind(n[3])},s=i.bind(n[0]);for(let e in o)Object.defineProperty(s,e,{enumerable:!1,writable:!1,configurable:!1,value:o[e]});return s}();var r={SINGLE_LINE_HIGHLIGHT_CLASS:"editableArea--single-line",MULTI_LINE_HIGHLIGHT_CLASS:"editableArea--multi-line"};var a=function(e,t,i){const n=i.Range,o=function(e,t){const i=e.range,n=t.range;if(i[0]n)throw new Error("Provided Start Line("+e+") is out of bounds. Max Lines in content is "+n);o[t]=e;break;case 1:{let n=e;const s=o[0],r=i[s-1].length;if(n<0){if(n=r-Math.abs(n),n<0)throw new Error("Provided Start Column("+e+") is out of bounds. Max Column in line "+s+" is "+r)}else if(n>r+1)throw new Error("Provided Start Column("+e+") is out of bounds. Max Column in line "+s+" is "+r);o[t]=n}break;case 2:{let i=e;if(i<0){if(i=n-Math.abs(e),i<0)throw new Error("Provided End Line("+e+") is out of bounds. Max Lines in content is "+n);in)throw new Error("Provided End Line("+e+") is out of bounds. Max Lines in content is "+n);o[t]=i}break;case 3:{let n=e;const s=o[2],r=i[s-1].length;if(n<0){if(n=r-Math.abs(n),n<0)throw new Error("Provided End Column("+e+") is out of bounds. Max Column in line "+s+" is "+r)}else if(n>r+1)throw new Error("Provided Start Column("+e+") is out of bounds. Max Column in line "+s+" is "+r);o[t]=n}}}),o}(e.range,i),s=o[0],r=o[1],a=o[2],l=o[3];e._originalRange=o.slice(),e.range=new n(s,r,a,l),e.index=t,e.allowMultiline||(e.allowMultiline=n.spansMultipleLines(e.range)),e.label||(e.label=`[${s},${r} -> ${a}${l}]`)})},h=function(){return a.reduce(function(e,t){return e[t.label]={allowMultiline:t.allowMultiline||!1,index:t.index,range:Object.assign({},t.range),originalRange:t._originalRange.slice()},e},{})},d=function(){return Promise.resolve().then(function(){e.editInRestrictedArea=!0,e.undo(),e.editInRestrictedArea=!1,e._hasHighlight&&e._oldDecorationsSource&&(e.deltaDecorations(e._oldDecorations,e._oldDecorationsSource),e._oldDecorationsSource.forEach(function(t){t.range=e.getDecorationRange(t.id)}))})},c=function(t,i,n,o,s,r){let l=i.endLineNumber,h=i.endColumn;t.prevRange=i,t.range=i.setEndPosition(n,o);const d=a.length;let c=s.length;const u=o-h,g=n-l,p=e._currentCursorPositions||[],m=p.length;if(c!==m&&(s=s.filter(function(e){const t=e.range;for(let e=0;el)break;i.startColumn+=u,i.endColumn+=u,t.range=i}for(let e=r+1;el){rangeMap[i.toString()]=o;break}i.startColumn+=u,i.endColumn+=u,t.range=i,rangeMap[i.toString()]=o}}},u=function(){console.debug("handler for unhandled promise rejection")},g=function(e){for(let t in e){const i=e[t];i.range=i.prevRange}},p=function(e,t){return!e.allowMultiline&&t.includes("\n")},m=function(e,t,i){return e.validate&&!e.validate(t,i,e.lastInfo)},f={_isRestrictedModel:!0,_isRestrictedValueValid:!0,_editableRangeChangeListener:[],_isCursorAtCheckPoint:function(t){t.some(function(t){const i=t.lineNumber,n=t.column,o=a.length;for(let t=0;t","ranges","Please refer constrained editor documentation for proper structure"))}throw new Error(o("ICodeEditor","editorInstance","This type interface can be found in monaco editor documentation"))},removeRestrictionsIn:function(e){if(r(e)){const t=e.uri.toString(),n=i[t];return n?n.disposeRestrictions():(console.warn("Current Model is not a restricted Model"),!1)}throw new Error(o("ICodeEditor","editorInstance","This type interface can be found in monaco editor documentation"))},disposeConstrainer:function(){if(h._editorInstance){const e=h._editorInstance.getDomNode();e&&e.removeEventListener("keydown",h._listener),h._onChangeModelDisposable&&h._onChangeModelDisposable.dispose(),delete h._listener,delete h._editorInstance._isInDevMode,delete h._editorInstance._devModeAction,delete h._editorInstance,delete h._onChangeModelDisposable;for(let e in i)delete i[e];return!0}return!1},toggleDevMode:function(){h._editorInstance._isInDevMode?(h._editorInstance._isInDevMode=!1,h._editorInstance._devModeAction.dispose(),delete h._editorInstance._devModeAction):(h._editorInstance._isInDevMode=!0,h._editorInstance._devModeAction=h._editorInstance.addAction({id:"showRange",label:"Show Range in console",contextMenuGroupId:"navigation",contextMenuOrder:1.5,run:function(e){const t=e.getSelections().reduce(function(e,{startLineNumber:t,endLineNumber:i,startColumn:n,endColumn:o}){return e.push("range : "+JSON.stringify([t,n,i,o])),e},[]).join("\n");console.log("Selected Ranges : \n"+JSON.stringify(t,null,2))}}))}};for(let e in c)Object.defineProperty(d,e,{enumerable:!1,writable:!1,configurable:!1,value:c[e]});return Object.freeze(d)},h=i(9416),d=i(9201),c=i(2742),u=i(6362);function g(e,t){var i=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),i.push.apply(i,n)}return i}function p(e){for(var t=1;t{class t extends e.PluginBase{construct(e){this.element=e,this.elementObserver=null,this.config=this.snowboard.dataConfig(this,e),this.events=this.snowboard["backend.ui.eventHandler"](this,"backend.formwidget.codeeditor"),this.alias=this.config.get("alias"),this.monaco=d,this.model=null,this.resizeListener=!1,this.visibilityListener=!1,this.clickListener=!1,this.clickStartedInEditor=!1,this.editor=null,this.container=this.element.querySelector(".editor-container"),this.valueBag=this.element.querySelector("[data-value-bag]"),this.statusBar=this.element.querySelector("[data-status-bar]"),this.statusBar&&(this.language=this.statusBar.querySelector(".language"),this.position=this.statusBar.querySelector(".position")),this.fullscreen=!1,this.cachedThemes={},this.resizeThrottle=null,this.savedState=null,this.dropHandlers=null,this.callbacks={fullScreenChange:()=>this.onFullScreenChange(),resize:()=>{clearTimeout(this.resizeThrottle),this.resizeThrottle=setTimeout(()=>this.onResize(),80)},click:e=>this.checkEditorClick(e),visibilityChange:()=>this.onVisibilityChange()},this.keybindings=[],this.customLineNumbering=null,this.disposables=[],this.observeElement()}defaults(){return{alias:null,autoCloseTags:!0,bracketColors:!1,codeFolding:!0,displayIndentGuides:!0,fontSize:12,highlightActiveLine:!0,language:"html",margin:0,readOnly:!1,semanticHighlighting:!0,selectionHighlighting:!0,showColors:!0,showGutter:!0,showInvisibles:!1,showMinimap:!0,showOccurrences:!0,showPrintMargin:!1,showScrollbar:!0,showSelectionOccurrences:!0,showSuggestions:!0,tabSize:4,theme:"vs-dark",useSoftTabs:!0,wordWrap:!0}}destruct(){this.dispose(),this.savedState&&this.savedState.model&&(this.savedState.model.dispose(),this.savedState=null),this.elementObserver&&this.elementObserver.disconnect(),this.visibilityListener&&(document.removeEventListener("visibilitychange",this.callbacks.visibilityChange),this.visibilityListener=!1),this.clickListener&&(document.removeEventListener("click",this.callbacks.click,{capture:!0}),this.clickListener=!1)}dispose(){this.editor&&(this.savedState={view:this.editor.saveViewState(),model:this.model}),this.disposables.length>0&&(this.disposables.forEach(e=>{e.dispose()}),this.disposables=[]),this.resizeListener&&(window.removeEventListener("resize",this.callbacks.resize),this.resizeListener=!1),this.dropHandlers&&(this.dropHandlers.editorDom.removeEventListener("dragover",this.dropHandlers.onDragOver),this.dropHandlers.editorDom.removeEventListener("drop",this.dropHandlers.onDrop),this.dropHandlers=null),this.model=null,this.editor&&(this.editor.dispose(),this.editor=null),this.events.fire("dispose",this)}observeElement(){this.elementObserver=new IntersectionObserver(e=>this.onObserve(e)),this.elementObserver.observe(this.element)}onObserve(e){e[0].isIntersecting?this.createEditor():this.dispose()}createEditor(){if(this.editor)return;this.container.style.height=null,this.container.style.height=Math.round(Number(getComputedStyle(this.container).height.replace("px","")))+"px";const e=this.getConfigOptions();this.savedState&&this.savedState.model?e.model=this.savedState.model:e.model=d.editor.createModel(this.valueBag.value,this.config.get("language")),this.editor=d.editor.create(this.element.querySelector(".editor-container"),e),window.jQuery&&window.jQuery(this.element).data("oc.codeEditor",this),this.attachListeners(),this.attachDropHandler(),this.loadTheme(),this.updateLanguage(),this.enableStatusBarActions(),this.registerKeyBindings(),this.registerDefaultKeyBindings(),this.savedState&&(this.savedState.view&&this.editor.restoreViewState(this.savedState.view),this.savedState=null),this.events.fire("create",this,this.editor)}refresh(){this.dispose(),window.requestAnimationFrame(()=>this.createEditor())}getConfigOptions(){const e={automaticLayout:!0,"bracketPairColorization.enabled":this.config.get("bracketColors"),colorDecorators:this.config.get("showColors"),detectIndentation:!1,folding:this.config.get("codeFolding"),fontSize:this.config.get("fontSize"),guides:{bracketPairs:!!this.config.get("bracketColors")&&"active",bracketPairsHorizontal:!!this.config.get("bracketColors")&&"active",indentation:this.config.get("displayIndentGuides")},insertSpaces:this.config.get("useSoftTabs"),language:this.config.get("language"),lineNumbers:this.customLineNumbering?this.customLineNumbering:this.config.get("showGutter")?"on":"off",minimap:{enabled:this.config.get("showMinimap")},occurrencesHighlight:this.config.get("showOccurrences")?"singleFile":"off",quickSuggestions:this.config.get("showSuggestions"),renderLineHighlight:this.getLineHighlightOption(),renderWhitespace:this.config.get("showInvisibles")?"all":"selection",scrollbar:{horizontalHasArrows:this.config.get("showScrollbar"),horizontalScrollbarSize:this.config.get("showScrollbar")?10:0,horizontalSliderSize:this.config.get("showScrollbar")?10:6,verticalHasArrows:this.config.get("showScrollbar"),verticalScrollbarSize:this.config.get("showScrollbar")?10:0,verticalSliderSize:this.config.get("showScrollbar")?10:6,useShadows:this.config.get("showScrollbar")},scrollBeyondLastLine:!1,selectionHighlight:this.config.get("showSelectionOccurrences"),"semanticHighlighting.enabled":!!this.config.get("semanticHighlighting")&&"configuredByTheme",tabSize:this.config.get("tabSize"),theme:this.config.get("themeVs")};return"fluid"===this.config.get("wordWrap")?e.wordWrap="on":"number"==typeof this.config.get("wordWrap")?(e.wordWrap="bounded",e.wordWrapColumn=this.config.get("wordWrap")):e.wordWrap="off",this.config.get("showPrintMargin")&&(e.rulers=[80]),e}getLineHighlightOption(){return this.config.get("highlightActiveLine")?this.config.get("showGutter")?"all":"line":"none"}getEditor(){return this.editor}getModel(){return this.model}attachListeners(){this.model=this.editor.getModel(),this.disposables.push(this.model.onDidChangeContent(()=>{this.valueBag.value=this.model.getValue(),this.events.fire("input",this.valueBag.value,this,this.editor)})),this.disposables.push(this.editor.onDidChangeCursorPosition(e=>{this.updatePosition(e.position),this.events.fire("position",e)})),this.disposables.push(this.editor.onDidChangeCursorSelection(e=>{this.events.fire("selection",e)})),this.disposables.push(this.editor.onMouseDown(()=>{this.clickStartedInEditor=!0})),this.disposables.push(this.editor.onMouseUp(()=>{setTimeout(()=>{this.clickStartedInEditor=!1},20)})),this.clickListener||(document.addEventListener("click",this.callbacks.click,{capture:!0}),this.clickListener=!0),window.addEventListener("resize",this.callbacks.resize),this.resizeListener=!0,this.visibilityListener||(document.addEventListener("visibilitychange",this.callbacks.visibilityChange),this.visibilityListener=!0)}attachDropHandler(){const e=this.editor.getDomNode();if(!e)return;const t=e=>{if(e.dataTransfer&&e.dataTransfer.types.includes("text/plain")){e.preventDefault(),e.dataTransfer.dropEffect="copy";const t=this.editor.getTargetAtClientPoint(e.clientX,e.clientY);t&&t.position&&this.editor.setPosition(t.position)}},i=e=>{const t=e.dataTransfer?.getData("text/plain");if(!t)return;e.preventDefault(),e.stopPropagation();const i=this.editor.getTargetAtClientPoint(e.clientX,e.clientY);i&&i.position&&(this.editor.setPosition(i.position),this.editor.focus(),this.insert(t))};e.addEventListener("dragover",t),e.addEventListener("drop",i),this.dropHandlers={editorDom:e,onDragOver:t,onDrop:i}}setConfig(e,t){this.config.set(e,t),this.editor&&(["showPrintMargin"].includes(e)?this.refresh():this.editor.updateOptions(this.getConfigOptions()))}getValue(){return this.model.getValue()}setValue(e){this.model.setValue(e)}focus(){this.editor.focus()}setMarkers(e,t){d.editor.setModelMarkers(this.editor.getModel(),e,t)}setDecorations(e,t){this._decorationIds||(this._decorationIds={});const i=this._decorationIds[e]||[],n=this.editor.deltaDecorations(i,t);this._decorationIds[e]=n}getPosition(){return this.editor.getPosition()}getSelection(){return this.editor.getSelection()}getSafeSelection(){const e=this.editor.getSelection();return new d.Selection(e.startLineNumber,e.startColumn,e.endLineNumber,e.endColumn)}getSelections(){return this.editor.getSelections()}insert(e){return this.model.pushEditOperations(this.editor.getSelections(),[{forceMoveMarkers:!0,range:this.editor.getSelection(),text:e}])}wrap(e,t){return this.editor.getSelection().isEmpty()?this.insert(`${e}${t}`):this.model.pushEditOperations(this.editor.getSelections(),[{forceMoveMarkers:!0,range:this.editor.getSelection(),text:`${e}${this.editor.getModel().getValueInRange(this.editor.getSelection())}${t}`}],()=>[this.editor.getSelection()])}unwrap(e,t){if(this.editor.getSelection().isEmpty())return this.editor.getSelection();let i=this.editor.getModel().getValueInRange(this.editor.getSelection());return i.startsWith(e)&&(i=i.substring(e.length)),i.endsWith(t)&&(i=i.substring(0,i.length-t.length)),this.model.pushEditOperations(this.editor.getSelections(),[{forceMoveMarkers:!0,range:this.editor.getSelection(),text:i}],()=>[this.editor.getSelection()])}find(e,t){return this.findAll(e,t)[0]||null}findAll(e,t){const i=e instanceof RegExp?e.source:e;return this.model.findMatches(i,!0,e instanceof RegExp,t||!1,null,!0,1)}replace(e,t,i,n=!0){if("string"!=typeof e&&!(e instanceof RegExp))return this.model.pushEditOperations([d.Selection.fromRange(e)],[{forceMoveMarkers:!1,range:new d.Range(e.startLineNumber,e.startColumn,e.endLineNumber,e.endColumn),text:n?this.alignText(t,e.startColumn):t}]);const o=this.find(e,i);return o?this.model.pushEditOperations(this.editor.getSelections(),[{forceMoveMarkers:!1,range:new d.Range(o.range.startLineNumber,o.range.startColumn,o.range.endLineNumber,o.range.endColumn),text:n?this.alignText(t,e.startColumn):t}]):void 0}alignText(e,t){return e.split("\n").map((e,i)=>0===i?e:`${" ".repeat(t-1)}${e}`).join("\n")}setLanguage(e){d.editor.setModelLanguage(this.model,e),this.setConfig("language",e),this.updateLanguage()}updateLanguage(){this.language&&(this.language.innerText=this.getConfigOptions().language.toUpperCase())}loadTheme(e){const t=e||this.config.get("theme"),i=t.replace(/[^a-z0-9]+/g,"");return"vs"===t?(d.editor.setTheme("vs"),this.setConfig("theme","vs"),this.setConfig("themeVs","vs"),void this.updateStatusBarColor({colors:{"editor.foreground":"#000000","editor.background":"#ffffff"}})):"vs-dark"===t?(d.editor.setTheme("vs-dark"),this.setConfig("theme","vs-dark"),this.setConfig("themeVs","vs-dark"),void this.updateStatusBarColor({colors:{"editor.foreground":"#d4d4d4","editor.background":"#1E1E1E"}})):void(this.cachedThemes[t]?(d.editor.setTheme(i),this.setConfig("theme",t),this.setConfig("themeVs",i),this.updateStatusBarColor(this.cachedThemes[t])):this.fetchTheme(t).then(({format:e,data:n})=>{let o;o="json"===e?this.convertJsonTheme(n):this.convertTmTheme(n),this.cachedThemes[t]=o,d.editor.defineTheme(i,o),d.editor.setTheme(i),this.setConfig("theme",t),this.setConfig("themeVs",i),this.updateStatusBarColor(o)}).catch(()=>{}))}async fetchTheme(e){let t=e;e.includes(".")||(t=`${e}.tmTheme`);const i=t.endsWith(".json")?"json":"tmTheme",n=`${window.Snowboard.url().asset("/modules/backend/formwidgets/codeeditor/assets/themes/")}${t}`,o=await fetch(n);if(!o.ok)throw new Error(`Theme "${e}" not found`);return{format:i,data:await o.text()}}convertJsonTheme(e){const t=JSON.parse(e),i={base:"light"===t.type?"vs":"vs-dark",inherit:!0,rules:[],colors:{}};return t.tokenColors&&Array.isArray(t.tokenColors)&&t.tokenColors.forEach(e=>{if(!e.scope)return;(Array.isArray(e.scope)?e.scope:e.scope.split(",").map(e=>e.trim())).forEach(t=>{const n={token:t};e.settings&&(e.settings.foreground&&(n.foreground=e.settings.foreground.replace("#","")),e.settings.background&&(n.background=e.settings.background.replace("#","")),e.settings.fontStyle&&(n.fontStyle=e.settings.fontStyle)),i.rules.push(n)})}),t.colors&&Object.keys(t.colors).forEach(e=>{i.colors[e]=t.colors[e]}),i}convertTmTheme(e){const t=(0,h.qg)(e),i=this.mapGlobalColors(t.settings.shift().settings);t.gutterSettings&&(t.gutterSettings.background&&(i["editorGutter.background"]=this.parseColor(t.gutterSettings.background)),t.gutterSettings.foreground&&(i["editorLineNumber.foreground"]=this.parseColor(t.gutterSettings.foreground)));const n=[{token:"",foreground:i["editor.foreground"].replace(/^#/,""),background:i["editor.background"].replace(/^#/,"")}];return t.settings.forEach(e=>{if(!e.scope)return;const t={token:e.scope};e.settings.foreground&&(t.foreground=this.parseColor(e.settings.foreground).replace(/^#/,"")),e.settings.background&&(t.background=this.parseColor(e.settings.background).replace(/^#/,"")),e.settings.fontStyle&&(t.fontStyle=e.settings.fontStyle),n.push(t)}),{base:this.isDarkTheme(i["editor.background"])?"vs-dark":"vs",inherit:!1,rules:this.populateMissingScopes(n),colors:i}}mapGlobalColors(e){const t={};return[{tm:"foreground",mn:"editor.foreground"},{tm:"background",mn:"editor.background"},{tm:"selection",mn:"editor.selectionBackground"},{tm:"inactiveSelection",mn:"editor.inactiveSelectionBackground"},{tm:"selectionHighlightColor",mn:"editor.selectionHighlightBackground"},{tm:"findMatchHighlight",mn:"editor.findMatchHighlightBackground"},{tm:"currentFindMatchHighlight",mn:"editor.findMatchBackground"},{tm:"hoverHighlight",mn:"editor.hoverHighlightBackground"},{tm:"wordHighlight",mn:"editor.wordHighlightBackground"},{tm:"wordHighlightStrong",mn:"editor.wordHighlightStrongBackground"},{tm:"findRangeHighlight",mn:"editor.findRangeHighlightBackground"},{tm:"findMatchHighlight",mn:"peekViewResult.matchHighlightBackground"},{tm:"referenceHighlight",mn:"peekViewEditor.matchHighlightBackground"},{tm:"lineHighlight",mn:"editor.lineHighlightBackground"},{tm:"rangeHighlight",mn:"editor.rangeHighlightBackground"},{tm:"guide",mn:"editorIndentGuide.background"},{tm:"activeGuide",mn:"editorIndentGuide.activeBackground"},{tm:"selectionBorder",mn:"editor.selectionHighlightBorder"}].forEach(i=>{e[i.tm]&&(t[i.mn]=this.parseColor(e[i.tm]))}),t}parseColor(e){let t=e;if(!t.length)return null;if(4===t.length&&(t=e.replace(/[a-fA-F\d]/g,"$&$&")),7===t.length)return t;if(9===e.length)return e;if(!e.match(/^#(..)(..)(..)(..)$/))return e;const i=e.match(/^#(..)(..)(..)(..)$/).slice(1).map(e=>parseInt(e,16));return i[3]=(i[3]/255).toPrecision(2),`rgba(${i.join(", ")})`}rgbColor(e){return"object"==typeof e?e:"#"===e[0]?e.match(/^#(..)(..)(..)/).slice(1).map(e=>parseInt(e,16)):e.match(/\(([^,]+),([^,]+),([^,]+)/).slice(1).map(e=>parseInt(e,10))}isDarkTheme(e){const t=this.rgbColor(e);return(.21*t[0]+.72*t[1]+.07*t[2])/255<.5}populateMissingScopes(e){const t={};Object.entries({comment:["comment.block","comment.line"],number:["constant.numeric","constant.number","string.number"],regexp:["string.regexp"],tag:["meta.tag","entity.name.tag"],"tag.css":["keyword"],metatag:["meta.tag","declaration.tag","constant.language","entity.name.tag"],annotation:["meta.embedded","meta.annotation","string.annotation","comment.block","comment.line"],attribute:["entity.other.attribute-name","support.type.property-name"],identifier:["entity.name.function"],type:["support.type","support.function"],operator:["support.constant","constant.numeric","constant.number","string.number","support"],"attribute.name":["support.type","support.constant","entity.other.attribute-name","support.type.property-name"],"attribute.name.html":["entity.other.attribute-name.html","entity.other.attribute-name"],"attribute.value.html":["string.quoted.double.html","string.quoted.single.html","string.quoted.double","string.quoted.single","string"],"attribute.value.unit":["keyword.unit","support.unit","keyword","support","number","string.number","constant.numeric","constant.number"],"attribute.value.number":["number","string.number","constant.numeric","constant.number"]}).forEach(([e,i])=>{t[e]={scope:e,map:i,currentSettings:null,currentRank:null}}),e.forEach(e=>{if(!e.token)return;e.token.split(/, +/).forEach((i,n)=>{i.split(/ +/).forEach((i,o)=>{const s=Object.values(t).filter(e=>e.map.filter(e=>i.startsWith(e)).length>0);s.length&&s.forEach(s=>{const r=10-n-2*o-(s.map.includes(i)?s.map.indexOf(i):5);null!==s.currentRank&&s.currentRank>=r||(t[s.scope].currentSettings={},t[s.scope].currentRank=r,e.foreground&&(t[s.scope].currentSettings.foreground=e.foreground),e.background&&(t[s.scope].currentSettings.background=e.background),e.fontStyle&&(t[s.scope].currentSettings.fontStyle=e.fontStyle))})})})}),Object.values(t).forEach(t=>{if(!t.currentSettings)return;if(e.some(e=>e.token===t.scope))return;const i={token:t.scope};t.currentSettings.foreground&&(i.foreground=t.currentSettings.foreground),t.currentSettings.background&&(i.background=t.currentSettings.background),t.currentSettings.fontStyle&&(i.fontStyle=t.currentSettings.fontStyle),e.push(i)});const i=[];return e.forEach(e=>{if(-1===e.token.indexOf(","))return void i.push(e);e.token.split(/, +/).forEach(t=>{i.push({token:t,foreground:e.foreground,background:e.background,fontStyle:e.fontStyle})})}),i}updatePosition(e){this.position&&(this.position.innerText=`Line ${e.lineNumber}, Column ${e.column}`)}updateStatusBarColor(e){if(!this.statusBar)return;const t=e.colors["editor.foreground"],i=e.colors["editor.background"];this.isDarkTheme(i)?this.statusBar.classList.add("is-dark"):this.statusBar.classList.remove("is-dark"),this.statusBar.style.color=t,this.statusBar.style.backgroundColor=i,this.container.style.backgroundColor=i}enableStatusBarActions(){if(!this.statusBar)return;const e=this.statusBar.querySelector("[data-full-screen]");e.addEventListener("click",()=>{this.fullscreen?document.exitFullscreen():this.element.requestFullscreen({navigationUI:"hide"}).then(()=>{this.fullscreen=!0,e.classList.add("active"),this.element.addEventListener("fullscreenchange",this.callbacks.fullScreenChange),this.editor&&window.requestAnimationFrame(()=>{this.editor.layout()})})})}onFullScreenChange(){document.fullscreenElement||(this.fullscreen=!1,this.statusBar&&this.statusBar.querySelector("[data-full-screen]").classList.remove("active"),this.element.removeEventListener("fullscreenchange",this.callbacks.fullScreenChange),this.editor&&window.requestAnimationFrame(()=>{this.editor.layout()}))}onResize(){this.editor&&this.editor.layout()}onVisibilityChange(){document.hidden?this.dispose():this.createEditor()}fromLine(e){if(e<=1)return void(this.customLineNumbering=null);const t=this.getModel().getFullModelRange().endLineNumber,i=this.getModel().getFullModelRange().endColumn;if(e>t)throw this.customLineNumbering=null,new Error("The line number is greater than the number of lines in the editor.");const n=new d.Range(1,1,e-1,i),o=new d.Range(e,1,t,i),s=l(d);s.initializeIn(this.editor),s.addRestrictionsTo(this.getModel(),[{range:[o.startLineNumber,o.startColumn,o.endLineNumber,o.endColumn],allowMultiline:!0}]),this.editor.setHiddenAreas([n]),this.config.get("showGutter")&&(this.customLineNumbering=t=>t>=e?String(t-e+1):"",this.editor.updateOptions(this.getConfigOptions()))}addKeyBinding(e,t){const i=this.normalizeKeyBinding(e);if(this.keybindings.push({keybinding:i,callback:t}),this.editor){const e=d.KeyCode[`Key${i.key.toUpperCase()}`];let n=0;i.shift&&(n|=d.KeyMod.Shift),i.ctrl&&(n|=d.KeyMod.CtrlCmd),i.alt&&(n|=d.KeyMod.Alt),n|=e,this.editor.addCommand(n,t)}}removeKeyBinding(e){const t=this.normalizeKeyBinding(e),i=this.keybindings.findIndex(e=>e.keybinding===t);-1!==i&&(this.keybindings[i].callback=()=>{})}normalizeKeyBinding(e){let t={key:null,ctrl:!1,alt:!1,shift:!1};return"string"==typeof e?e.startsWith("Shift+Ctrl+")?(t.key=e.replace("Shift+Ctrl+",""),t.shift=!0,t.ctrl=!0):e.startsWith("Shift+Alt+")?(t.key=e.replace("Shift+Alt+",""),t.shift=!0,t.alt=!0):e.startsWith("Ctrl+")?(t.key=e.replace("Ctrl+",""),t.ctrl=!0):e.startsWith("Alt+")&&(t.key=e.replace("Alt+",""),t.alt=!0):t=p(p({},t),e),t}registerKeyBindings(){0!==this.keybindings.length&&this.keybindings.forEach(e=>{const t=d.KeyCode[`Key${e.keybinding.key.toUpperCase()}`];let i=0;e.keybinding.shift&&(i|=d.KeyMod.Shift),e.keybinding.ctrl&&(i|=d.KeyMod.CtrlCmd),e.keybinding.alt&&(i|=d.KeyMod.Alt),i|=t,this.editor.addCommand(i,e.callback)})}registerDefaultKeyBindings(){this.editor.addCommand(d.KeyMod.CtrlCmd|d.KeyMod.Shift|d.KeyCode.KeyD,()=>{const e=this.editor.getSelection(),t=this.editor.getModel(),i=e.startLineNumber,n=e.endLineNumber,o=t.getLineMaxColumn(n),s=t.getValueInRange(new d.Range(i,1,n,o)),r=n-i+1;t.pushEditOperations([e],[{range:new d.Range(n,o,n,o),text:"\n"+s}],()=>[new d.Selection(i+r,e.startColumn,n+r,e.endColumn)])}),this.editor.addCommand(d.KeyMod.CtrlCmd|d.KeyMod.Shift|d.KeyCode.KeyF,()=>{this.fullscreen?document.exitFullscreen():this.element.requestFullscreen({navigationUI:"hide"}).then(()=>{this.fullscreen=!0,this.statusBar&&this.statusBar.querySelector("[data-full-screen]").classList.add("active"),this.element.addEventListener("fullscreenchange",this.callbacks.fullScreenChange),this.editor&&window.requestAnimationFrame(()=>this.editor.layout())})})}checkEditorClick(e){this.clickStartedInEditor&&!this.element.contains(e.target)&&(e.stopImmediatePropagation(),e.preventDefault()),this.clickStartedInEditor=!1}addCodeLens(e,t,i=null){this.disposables.push(d.languages.registerCodeLensProvider(e,{provideCodeLenses:(e,i)=>t(e,i),resolveCodeLens:(e,t,n)=>i(e,t,n)??t}))}}e.addPlugin("backend.formwidgets.codeeditor",t),e["backend.ui.widgetHandler"]().register("codeeditor","backend.formwidgets.codeeditor")})(window.Snowboard)},8422:function(e,t){"use strict";t.byteLength=function(e){var t=a(e),i=t[0],n=t[1];return 3*(i+n)/4-n},t.toByteArray=function(e){var t,i,s=a(e),r=s[0],l=s[1],h=new o(function(e,t,i){return 3*(t+i)/4-i}(0,r,l)),d=0,c=l>0?r-4:r;for(i=0;i>16&255,h[d++]=t>>8&255,h[d++]=255&t;2===l&&(t=n[e.charCodeAt(i)]<<2|n[e.charCodeAt(i+1)]>>4,h[d++]=255&t);1===l&&(t=n[e.charCodeAt(i)]<<10|n[e.charCodeAt(i+1)]<<4|n[e.charCodeAt(i+2)]>>2,h[d++]=t>>8&255,h[d++]=255&t);return h},t.fromByteArray=function(e){for(var t,n=e.length,o=n%3,s=[],r=16383,a=0,l=n-o;al?l:a+r));1===o?(t=e[n-1],s.push(i[t>>2]+i[t<<4&63]+"==")):2===o&&(t=(e[n-2]<<8)+e[n-1],s.push(i[t>>10]+i[t>>4&63]+i[t<<2&63]+"="));return s.join("")};for(var i=[],n=[],o="undefined"!=typeof Uint8Array?Uint8Array:Array,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",r=0;r<64;++r)i[r]=s[r],n[s.charCodeAt(r)]=r;function a(e){var t=e.length;if(t%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var i=e.indexOf("=");return-1===i&&(i=t),[i,i===t?0:4-i%4]}function l(e){return i[e>>18&63]+i[e>>12&63]+i[e>>6&63]+i[63&e]}function h(e,t,i){for(var n,o=[],s=t;s + * @license MIT + */function r(){return l.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function a(e,t){if(r()=r())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+r().toString(16)+" bytes");return 0|e}function p(e,t){if(l.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var i=e.length;if(0===i)return 0;for(var n=!1;;)switch(t){case"ascii":case"latin1":case"binary":return i;case"utf8":case"utf-8":case void 0:return z(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*i;case"hex":return i>>>1;case"base64":return H(e).length;default:if(n)return z(e).length;t=(""+t).toLowerCase(),n=!0}}function m(e,t,i){var n=!1;if((void 0===t||t<0)&&(t=0),t>this.length)return"";if((void 0===i||i>this.length)&&(i=this.length),i<=0)return"";if((i>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return I(this,t,i);case"utf8":case"utf-8":return x(this,t,i);case"ascii":return E(this,t,i);case"latin1":case"binary":return N(this,t,i);case"base64":return L(this,t,i);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return M(this,t,i);default:if(n)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),n=!0}}function f(e,t,i){var n=e[t];e[t]=e[i],e[i]=n}function _(e,t,i,n,o){if(0===e.length)return-1;if("string"==typeof i?(n=i,i=0):i>2147483647?i=2147483647:i<-2147483648&&(i=-2147483648),i=+i,isNaN(i)&&(i=o?0:e.length-1),i<0&&(i=e.length+i),i>=e.length){if(o)return-1;i=e.length-1}else if(i<0){if(!o)return-1;i=0}if("string"==typeof t&&(t=l.from(t,n)),l.isBuffer(t))return 0===t.length?-1:v(e,t,i,n,o);if("number"==typeof t)return t&=255,l.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(e,t,i):Uint8Array.prototype.lastIndexOf.call(e,t,i):v(e,[t],i,n,o);throw new TypeError("val must be string, number or Buffer")}function v(e,t,i,n,o){var s,r=1,a=e.length,l=t.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(e.length<2||t.length<2)return-1;r=2,a/=2,l/=2,i/=2}function h(e,t){return 1===r?e[t]:e.readUInt16BE(t*r)}if(o){var d=-1;for(s=i;sa&&(i=a-l),s=i;s>=0;s--){for(var c=!0,u=0;uo&&(n=o):n=o;var s=t.length;if(s%2!=0)throw new TypeError("Invalid hex string");n>s/2&&(n=s/2);for(var r=0;r>8,o=i%256,s.push(o),s.push(n);return s}(t,e.length-i),e,i,n)}function L(e,t,i){return 0===t&&i===e.length?n.fromByteArray(e):n.fromByteArray(e.slice(t,i))}function x(e,t,i){i=Math.min(e.length,i);for(var n=[],o=t;o239?4:h>223?3:h>191?2:1;if(o+c<=i)switch(c){case 1:h<128&&(d=h);break;case 2:128==(192&(s=e[o+1]))&&(l=(31&h)<<6|63&s)>127&&(d=l);break;case 3:s=e[o+1],r=e[o+2],128==(192&s)&&128==(192&r)&&(l=(15&h)<<12|(63&s)<<6|63&r)>2047&&(l<55296||l>57343)&&(d=l);break;case 4:s=e[o+1],r=e[o+2],a=e[o+3],128==(192&s)&&128==(192&r)&&128==(192&a)&&(l=(15&h)<<18|(63&s)<<12|(63&r)<<6|63&a)>65535&&l<1114112&&(d=l)}null===d?(d=65533,c=1):d>65535&&(d-=65536,n.push(d>>>10&1023|55296),d=56320|1023&d),n.push(d),o+=c}return function(e){var t=e.length;if(t<=D)return String.fromCharCode.apply(String,e);var i="",n=0;for(;n0&&(e=this.toString("hex",0,i).match(/.{2}/g).join(" "),this.length>i&&(e+=" ... ")),""},l.prototype.compare=function(e,t,i,n,o){if(!l.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===i&&(i=e?e.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),t<0||i>e.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&t>=i)return 0;if(n>=o)return-1;if(t>=i)return 1;if(this===e)return 0;for(var s=(o>>>=0)-(n>>>=0),r=(i>>>=0)-(t>>>=0),a=Math.min(s,r),h=this.slice(n,o),d=e.slice(t,i),c=0;co)&&(i=o),e.length>0&&(i<0||t<0)||t>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var s=!1;;)switch(n){case"hex":return b(this,e,t,i);case"utf8":case"utf-8":return w(this,e,t,i);case"ascii":return C(this,e,t,i);case"latin1":case"binary":return y(this,e,t,i);case"base64":return S(this,e,t,i);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return k(this,e,t,i);default:if(s)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),s=!0}},l.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var D=4096;function E(e,t,i){var n="";i=Math.min(e.length,i);for(var o=t;on)&&(i=n);for(var o="",s=t;si)throw new RangeError("Trying to access beyond buffer length")}function A(e,t,i,n,o,s){if(!l.isBuffer(e))throw new TypeError('"buffer" argument must be a Buffer instance');if(t>o||te.length)throw new RangeError("Index out of range")}function O(e,t,i,n){t<0&&(t=65535+t+1);for(var o=0,s=Math.min(e.length-i,2);o>>8*(n?o:1-o)}function R(e,t,i,n){t<0&&(t=4294967295+t+1);for(var o=0,s=Math.min(e.length-i,4);o>>8*(n?o:3-o)&255}function P(e,t,i,n,o,s){if(i+n>e.length)throw new RangeError("Index out of range");if(i<0)throw new RangeError("Index out of range")}function F(e,t,i,n,s){return s||P(e,0,i,4),o.write(e,t,i,n,23,4),i+4}function B(e,t,i,n,s){return s||P(e,0,i,8),o.write(e,t,i,n,52,8),i+8}l.prototype.slice=function(e,t){var i,n=this.length;if((e=~~e)<0?(e+=n)<0&&(e=0):e>n&&(e=n),(t=void 0===t?n:~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),t0&&(o*=256);)n+=this[e+--t]*o;return n},l.prototype.readUInt8=function(e,t){return t||T(e,1,this.length),this[e]},l.prototype.readUInt16LE=function(e,t){return t||T(e,2,this.length),this[e]|this[e+1]<<8},l.prototype.readUInt16BE=function(e,t){return t||T(e,2,this.length),this[e]<<8|this[e+1]},l.prototype.readUInt32LE=function(e,t){return t||T(e,4,this.length),(this[e]|this[e+1]<<8|this[e+2]<<16)+16777216*this[e+3]},l.prototype.readUInt32BE=function(e,t){return t||T(e,4,this.length),16777216*this[e]+(this[e+1]<<16|this[e+2]<<8|this[e+3])},l.prototype.readIntLE=function(e,t,i){e|=0,t|=0,i||T(e,t,this.length);for(var n=this[e],o=1,s=0;++s=(o*=128)&&(n-=Math.pow(2,8*t)),n},l.prototype.readIntBE=function(e,t,i){e|=0,t|=0,i||T(e,t,this.length);for(var n=t,o=1,s=this[e+--n];n>0&&(o*=256);)s+=this[e+--n]*o;return s>=(o*=128)&&(s-=Math.pow(2,8*t)),s},l.prototype.readInt8=function(e,t){return t||T(e,1,this.length),128&this[e]?-1*(255-this[e]+1):this[e]},l.prototype.readInt16LE=function(e,t){t||T(e,2,this.length);var i=this[e]|this[e+1]<<8;return 32768&i?4294901760|i:i},l.prototype.readInt16BE=function(e,t){t||T(e,2,this.length);var i=this[e+1]|this[e]<<8;return 32768&i?4294901760|i:i},l.prototype.readInt32LE=function(e,t){return t||T(e,4,this.length),this[e]|this[e+1]<<8|this[e+2]<<16|this[e+3]<<24},l.prototype.readInt32BE=function(e,t){return t||T(e,4,this.length),this[e]<<24|this[e+1]<<16|this[e+2]<<8|this[e+3]},l.prototype.readFloatLE=function(e,t){return t||T(e,4,this.length),o.read(this,e,!0,23,4)},l.prototype.readFloatBE=function(e,t){return t||T(e,4,this.length),o.read(this,e,!1,23,4)},l.prototype.readDoubleLE=function(e,t){return t||T(e,8,this.length),o.read(this,e,!0,52,8)},l.prototype.readDoubleBE=function(e,t){return t||T(e,8,this.length),o.read(this,e,!1,52,8)},l.prototype.writeUIntLE=function(e,t,i,n){(e=+e,t|=0,i|=0,n)||A(this,e,t,i,Math.pow(2,8*i)-1,0);var o=1,s=0;for(this[t]=255&e;++s=0&&(s*=256);)this[t+o]=e/s&255;return t+i},l.prototype.writeUInt8=function(e,t,i){return e=+e,t|=0,i||A(this,e,t,1,255,0),l.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),this[t]=255&e,t+1},l.prototype.writeUInt16LE=function(e,t,i){return e=+e,t|=0,i||A(this,e,t,2,65535,0),l.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):O(this,e,t,!0),t+2},l.prototype.writeUInt16BE=function(e,t,i){return e=+e,t|=0,i||A(this,e,t,2,65535,0),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):O(this,e,t,!1),t+2},l.prototype.writeUInt32LE=function(e,t,i){return e=+e,t|=0,i||A(this,e,t,4,4294967295,0),l.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):R(this,e,t,!0),t+4},l.prototype.writeUInt32BE=function(e,t,i){return e=+e,t|=0,i||A(this,e,t,4,4294967295,0),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):R(this,e,t,!1),t+4},l.prototype.writeIntLE=function(e,t,i,n){if(e=+e,t|=0,!n){var o=Math.pow(2,8*i-1);A(this,e,t,i,o-1,-o)}var s=0,r=1,a=0;for(this[t]=255&e;++s=0&&(r*=256);)e<0&&0===a&&0!==this[t+s+1]&&(a=1),this[t+s]=(e/r|0)-a&255;return t+i},l.prototype.writeInt8=function(e,t,i){return e=+e,t|=0,i||A(this,e,t,1,127,-128),l.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},l.prototype.writeInt16LE=function(e,t,i){return e=+e,t|=0,i||A(this,e,t,2,32767,-32768),l.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):O(this,e,t,!0),t+2},l.prototype.writeInt16BE=function(e,t,i){return e=+e,t|=0,i||A(this,e,t,2,32767,-32768),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):O(this,e,t,!1),t+2},l.prototype.writeInt32LE=function(e,t,i){return e=+e,t|=0,i||A(this,e,t,4,2147483647,-2147483648),l.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):R(this,e,t,!0),t+4},l.prototype.writeInt32BE=function(e,t,i){return e=+e,t|=0,i||A(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):R(this,e,t,!1),t+4},l.prototype.writeFloatLE=function(e,t,i){return F(this,e,t,!0,i)},l.prototype.writeFloatBE=function(e,t,i){return F(this,e,t,!1,i)},l.prototype.writeDoubleLE=function(e,t,i){return B(this,e,t,!0,i)},l.prototype.writeDoubleBE=function(e,t,i){return B(this,e,t,!1,i)},l.prototype.copy=function(e,t,i,n){if(i||(i=0),n||0===n||(n=this.length),t>=e.length&&(t=e.length),t||(t=0),n>0&&n=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),e.length-t=0;--o)e[o+t]=this[o+i];else if(s<1e3||!l.TYPED_ARRAY_SUPPORT)for(o=0;o>>=0,i=void 0===i?this.length:i>>>0,e||(e=0),"number"==typeof e)for(s=t;s55295&&i<57344){if(!o){if(i>56319){(t-=3)>-1&&s.push(239,191,189);continue}if(r+1===n){(t-=3)>-1&&s.push(239,191,189);continue}o=i;continue}if(i<56320){(t-=3)>-1&&s.push(239,191,189),o=i;continue}i=65536+(o-55296<<10|i-56320)}else o&&(t-=3)>-1&&s.push(239,191,189);if(o=null,i<128){if((t-=1)<0)break;s.push(i)}else if(i<2048){if((t-=2)<0)break;s.push(i>>6|192,63&i|128)}else if(i<65536){if((t-=3)<0)break;s.push(i>>12|224,i>>6&63|128,63&i|128)}else{if(!(i<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;s.push(i>>18|240,i>>12&63|128,i>>6&63|128,63&i|128)}}return s}function H(e){return n.toByteArray(function(e){if((e=function(e){return e.trim?e.trim():e.replace(/^\s+|\s+$/g,"")}(e).replace(V,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function U(e,t,i,n){for(var o=0;o=t.length||o>=e.length);++o)t[o+i]=e[o];return o}},298:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-action-bar{height:100%;white-space:nowrap}.monaco-action-bar .actions-container{align-items:center;display:flex;height:100%;margin:0 auto;padding:0;width:100%}.monaco-action-bar.vertical .actions-container{display:inline-block}.monaco-action-bar .action-item{align-items:center;cursor:pointer;display:block;justify-content:center;position:relative}.monaco-action-bar .action-item.disabled{cursor:default}.monaco-action-bar .action-item .codicon,.monaco-action-bar .action-item .icon{display:block}.monaco-action-bar .action-item .codicon{align-items:center;display:flex;height:16px;width:16px}.monaco-action-bar .action-label{border-radius:5px;font-size:11px;padding:3px}.monaco-action-bar .action-item.disabled .action-label,.monaco-action-bar .action-item.disabled .action-label:before,.monaco-action-bar .action-item.disabled .action-label:hover{opacity:.6}.monaco-action-bar.vertical{text-align:left}.monaco-action-bar.vertical .action-item{display:block}.monaco-action-bar.vertical .action-label.separator{border-bottom:1px solid #bbb;display:block;margin-left:.8em;margin-right:.8em;padding-top:1px}.monaco-action-bar .action-item .action-label.separator{background-color:#bbb;cursor:default;height:16px;margin:5px 4px!important;min-width:1px;padding:0;width:1px}.secondary-actions .monaco-action-bar .action-label{margin-left:6px}.monaco-action-bar .action-item.select-container{align-items:center;display:flex;flex:1;justify-content:center;margin-right:10px;max-width:170px;min-width:60px;overflow:hidden}.monaco-action-bar .action-item.action-dropdown-item{display:flex}.monaco-action-bar .action-item.action-dropdown-item>.action-label{margin-right:1px}",""]),t.A=o},9362:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-aria-container{left:-999em;position:absolute}",""]),t.A=o},9188:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-text-button{align-items:center;box-sizing:border-box;cursor:pointer;display:flex;justify-content:center;padding:4px;text-align:center;width:100%}.monaco-text-button:focus{outline-offset:2px!important}.monaco-text-button:hover{text-decoration:none!important}.monaco-button.disabled,.monaco-button.disabled:focus{cursor:default;opacity:.4!important}.monaco-text-button>.codicon{color:inherit!important;margin:0 .2em}.monaco-button-dropdown{cursor:pointer;display:flex}.monaco-button-dropdown.disabled{cursor:default}.monaco-button-dropdown>.monaco-button:focus{outline-offset:-1px!important}.monaco-button-dropdown.disabled>.monaco-button-dropdown-separator,.monaco-button-dropdown.disabled>.monaco-button.disabled,.monaco-button-dropdown.disabled>.monaco-button.disabled:focus{opacity:.4!important}.monaco-button-dropdown>.monaco-button.monaco-text-button{border-right-width:0!important}.monaco-button-dropdown .monaco-button-dropdown-separator{cursor:default;padding:4px 0}.monaco-button-dropdown .monaco-button-dropdown-separator>div{height:100%;width:1px}.monaco-button-dropdown>.monaco-button.monaco-dropdown-button{border-left-width:0!important}.monaco-description-button{flex-direction:column}.monaco-description-button .monaco-button-label{font-weight:500}.monaco-description-button .monaco-button-description{font-style:italic}.monaco-description-button .monaco-button-description,.monaco-description-button .monaco-button-label{align-items:center;display:flex;justify-content:center}.monaco-description-button .monaco-button-description>.codicon,.monaco-description-button .monaco-button-label>.codicon{color:inherit!important;margin:0 .2em}",""]),t.A=o},1742:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".codicon-wrench-subaction{opacity:.5}@keyframes codicon-spin{to{transform:rotate(1turn)}}.codicon-gear.codicon-modifier-spin,.codicon-loading.codicon-modifier-spin,.codicon-notebook-state-executing.codicon-modifier-spin,.codicon-sync.codicon-modifier-spin{animation:codicon-spin 1.5s steps(30) infinite}.codicon-modifier-disabled{opacity:.4}.codicon-loading,.codicon-tree-item-loading:before{animation-duration:1s!important;animation-timing-function:cubic-bezier(.53,.21,.29,.67)!important}",""]),t.A=o},6831:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,'.codicon[class*=codicon-]{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:inline-block;font:normal normal normal 16px/1 codicon;text-align:center;text-decoration:none;text-rendering:auto;text-transform:none;-moz-user-select:none;user-select:none;-webkit-user-select:none;-ms-user-select:none}',""]),t.A=o},3758:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".context-view{position:absolute}.context-view.fixed{all:initial;color:inherit;font-family:inherit;font-size:13px;position:fixed}",""]),t.A=o},3800:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-count-badge{border-radius:11px;box-sizing:border-box;display:inline-block;font-size:11px;font-weight:400;line-height:11px;min-height:18px;min-width:18px;padding:3px 6px;text-align:center}.monaco-count-badge.long{border-radius:2px;line-height:normal;min-height:auto;padding:2px 3px}",""]),t.A=o},2474:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-dropdown{height:100%;padding:0}.monaco-dropdown>.dropdown-label{align-items:center;cursor:pointer;display:flex;height:100%;justify-content:center}.monaco-dropdown>.dropdown-label>.action-label.disabled{cursor:default}.monaco-dropdown-with-primary{border-radius:5px;display:flex!important;flex-direction:row}.monaco-dropdown-with-primary>.action-container>.action-label{margin-right:0}.monaco-dropdown-with-primary>.dropdown-action-container>.monaco-dropdown>.dropdown-label .codicon[class*=codicon-]{font-size:12px;line-height:16px;margin-left:-3px;padding-left:0;padding-right:0}.monaco-dropdown-with-primary>.dropdown-action-container>.monaco-dropdown>.dropdown-label>.action-label{background-position:50%;background-repeat:no-repeat;background-size:16px;display:block}",""]),t.A=o},4254:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-findInput{position:relative}.monaco-findInput .monaco-inputbox{font-size:13px;width:100%}.monaco-findInput>.controls{position:absolute;right:2px;top:3px}.vs .monaco-findInput.disabled{background-color:#e1e1e1}.vs-dark .monaco-findInput.disabled{background-color:#333}.hc-light .monaco-findInput.highlight-0 .controls,.monaco-findInput.highlight-0 .controls{animation:monaco-findInput-highlight-0 .1s linear 0s}.hc-light .monaco-findInput.highlight-1 .controls,.monaco-findInput.highlight-1 .controls{animation:monaco-findInput-highlight-1 .1s linear 0s}.hc-black .monaco-findInput.highlight-0 .controls,.vs-dark .monaco-findInput.highlight-0 .controls{animation:monaco-findInput-highlight-dark-0 .1s linear 0s}.hc-black .monaco-findInput.highlight-1 .controls,.vs-dark .monaco-findInput.highlight-1 .controls{animation:monaco-findInput-highlight-dark-1 .1s linear 0s}@keyframes monaco-findInput-highlight-0{0%{background:rgba(253,255,0,.8)}to{background:transparent}}@keyframes monaco-findInput-highlight-1{0%{background:rgba(253,255,0,.8)}99%{background:transparent}}@keyframes monaco-findInput-highlight-dark-0{0%{background:hsla(0,0%,100%,.44)}to{background:transparent}}@keyframes monaco-findInput-highlight-dark-1{0%{background:hsla(0,0%,100%,.44)}99%{background:transparent}}",""]),t.A=o},1098:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,'.monaco-hover{animation:fadein .1s linear;box-sizing:initial;cursor:default;line-height:1.5em;overflow:hidden;position:absolute;-moz-user-select:text;user-select:text;-webkit-user-select:text;-ms-user-select:text;z-index:50}.monaco-hover.hidden{display:none}.monaco-hover a:hover{cursor:pointer}.monaco-hover .hover-contents:not(.html-hover-contents){padding:4px 8px}.monaco-hover .markdown-hover>.hover-contents:not(.code-hover-contents){word-wrap:break-word;max-width:500px}.monaco-hover .markdown-hover>.hover-contents:not(.code-hover-contents) hr{min-width:100%}.monaco-hover .code,.monaco-hover p,.monaco-hover ul{margin:8px 0}.monaco-hover code{font-family:var(--monaco-monospace-font)}.monaco-hover hr{border-left:0;border-right:0;box-sizing:border-box;height:1px;margin:4px -8px -4px}.monaco-hover .code:first-child,.monaco-hover p:first-child,.monaco-hover ul:first-child{margin-top:0}.monaco-hover .code:last-child,.monaco-hover p:last-child,.monaco-hover ul:last-child{margin-bottom:0}.monaco-hover ol,.monaco-hover ul{padding-left:20px}.monaco-hover li>p{margin-bottom:0}.monaco-hover li>ul{margin-top:0}.monaco-hover code{border-radius:3px;padding:0 .4em}.monaco-hover .monaco-tokenized-source{white-space:pre-wrap}.monaco-hover .hover-row.status-bar{font-size:12px;line-height:22px}.monaco-hover .hover-row.status-bar .actions{display:flex;padding:0 8px}.monaco-hover .hover-row.status-bar .actions .action-container{cursor:pointer;margin-right:16px}.monaco-hover .hover-row.status-bar .actions .action-container .action .icon{padding-right:4px}.monaco-hover .markdown-hover .hover-contents .codicon{color:inherit;font-size:inherit;vertical-align:middle}.monaco-hover .hover-contents a.code-link,.monaco-hover .hover-contents a.code-link:hover{color:inherit}.monaco-hover .hover-contents a.code-link:before{content:"("}.monaco-hover .hover-contents a.code-link:after{content:")"}.monaco-hover .hover-contents a.code-link>span{border-bottom:1px solid transparent;text-decoration:underline;text-underline-position:under}.monaco-hover .markdown-hover .hover-contents:not(.code-hover-contents):not(.html-hover-contents) span{display:inline-block;margin-bottom:4px}.monaco-hover-content .action-container a{-webkit-user-select:none;-moz-user-select:none;user-select:none}.monaco-hover-content .action-container.disabled{cursor:default;opacity:.4;pointer-events:none}',""]),t.A=o},6714:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-icon-label{display:flex;overflow:hidden;text-overflow:ellipsis}.monaco-icon-label:before{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;background-position:0;background-repeat:no-repeat;background-size:16px;display:inline-block;flex-shrink:0;height:22px;line-height:inherit!important;padding-right:6px;vertical-align:top;width:16px}.monaco-icon-label>.monaco-icon-label-container{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.monaco-icon-label>.monaco-icon-label-container>.monaco-icon-name-container>.label-name{color:inherit;white-space:pre}.monaco-icon-label>.monaco-icon-label-container>.monaco-icon-name-container>.label-name>.label-separator{margin:0 2px;opacity:.5}.monaco-icon-label>.monaco-icon-label-container>.monaco-icon-description-container>.label-description{font-size:.9em;margin-left:.5em;opacity:.7;white-space:pre}.monaco-icon-label.nowrap>.monaco-icon-label-container>.monaco-icon-description-container>.label-description{white-space:nowrap}.vs .monaco-icon-label>.monaco-icon-label-container>.monaco-icon-description-container>.label-description{opacity:.95}.monaco-icon-label.italic>.monaco-icon-label-container>.monaco-icon-description-container>.label-description,.monaco-icon-label.italic>.monaco-icon-label-container>.monaco-icon-name-container>.label-name{font-style:italic}.monaco-icon-label.deprecated{opacity:.66;text-decoration:line-through}.monaco-icon-label.italic:after{font-style:italic}.monaco-icon-label.strikethrough>.monaco-icon-label-container>.monaco-icon-description-container>.label-description,.monaco-icon-label.strikethrough>.monaco-icon-label-container>.monaco-icon-name-container>.label-name{text-decoration:line-through}.monaco-icon-label:after{font-size:90%;font-weight:600;margin:auto 16px 0 5px;opacity:.75;text-align:center}.monaco-list:focus .selected .monaco-icon-label,.monaco-list:focus .selected .monaco-icon-label:after{color:inherit!important}.monaco-list-row.focused.selected .label-description,.monaco-list-row.selected .label-description{opacity:.8}",""]),t.A=o},6330:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-inputbox{box-sizing:border-box;display:block;font-size:inherit;padding:0;position:relative}.monaco-inputbox.idle{border:1px solid transparent}.monaco-inputbox>.ibwrapper>.input,.monaco-inputbox>.ibwrapper>.mirror{padding:4px}.monaco-inputbox>.ibwrapper{height:100%;position:relative;width:100%}.monaco-inputbox>.ibwrapper>.input{border:none;box-sizing:border-box;color:inherit;display:inline-block;font-family:inherit;font-size:inherit;height:100%;line-height:inherit;resize:none;width:100%}.monaco-inputbox>.ibwrapper>input{text-overflow:ellipsis}.monaco-inputbox>.ibwrapper>textarea.input{-ms-overflow-style:none;display:block;outline:none;scrollbar-width:none}.monaco-inputbox>.ibwrapper>textarea.input::-webkit-scrollbar{display:none}.monaco-inputbox>.ibwrapper>textarea.input.empty{white-space:nowrap}.monaco-inputbox>.ibwrapper>.mirror{word-wrap:break-word;box-sizing:border-box;display:inline-block;left:0;position:absolute;top:0;visibility:hidden;white-space:pre-wrap;width:100%}.monaco-inputbox-container{text-align:right}.monaco-inputbox-container .monaco-inputbox-message{word-wrap:break-word;box-sizing:border-box;display:inline-block;font-size:12px;line-height:17px;margin-top:-1px;overflow:hidden;padding:.4em;text-align:left;width:100%}.monaco-inputbox .monaco-action-bar{position:absolute;right:2px;top:4px}.monaco-inputbox .monaco-action-bar .action-item{margin-left:2px}.monaco-inputbox .monaco-action-bar .action-item .codicon{background-repeat:no-repeat;height:16px;width:16px}",""]),t.A=o},6242:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-keybinding{align-items:center;display:flex;line-height:10px}.monaco-keybinding>.monaco-keybinding-key{border-radius:3px;border-style:solid;border-width:1px;display:inline-block;font-size:11px;margin:0 2px;padding:3px 5px;vertical-align:middle}.monaco-keybinding>.monaco-keybinding-key:first-child{margin-left:0}.monaco-keybinding>.monaco-keybinding-key:last-child{margin-right:0}.monaco-keybinding>.monaco-keybinding-key-separator{display:inline-block}.monaco-keybinding>.monaco-keybinding-key-chord-separator{width:6px}",""]),t.A=o},1504:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-list{height:100%;position:relative;white-space:nowrap;width:100%}.monaco-list.mouse-support{-moz-user-select:none;user-select:none;-webkit-user-select:none;-ms-user-select:none}.monaco-list>.monaco-scrollable-element{height:100%}.monaco-list-rows{height:100%;position:relative;width:100%}.monaco-list.horizontal-scrolling .monaco-list-rows{min-width:100%;width:auto}.monaco-list-row{box-sizing:border-box;overflow:hidden;position:absolute;width:100%}.monaco-list.mouse-support .monaco-list-row{cursor:pointer;touch-action:none}.monaco-list-row.scrolling{display:none!important}.monaco-list.element-focused,.monaco-list.selection-multiple,.monaco-list.selection-single{outline:0!important}.monaco-drag-image{border-radius:10px;display:inline-block;font-size:12px;padding:1px 7px;position:absolute;z-index:1000}.monaco-list-type-filter-message{box-sizing:border-box;height:100%;left:0;opacity:.7;padding:40px 1em 1em;pointer-events:none;position:absolute;text-align:center;top:0;white-space:normal;width:100%}.monaco-list-type-filter-message:empty{display:none}",""]),t.A=o},814:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-mouse-cursor-text{cursor:text}",""]),t.A=o},4486:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-progress-container{height:5px;overflow:hidden;width:100%}.monaco-progress-container .progress-bit{display:none;height:5px;left:0;position:absolute;width:2%}.monaco-progress-container.active .progress-bit{display:inherit}.monaco-progress-container.discrete .progress-bit{left:0;transition:width .1s linear}.monaco-progress-container.discrete.done .progress-bit{width:100%}.monaco-progress-container.infinite .progress-bit{animation-duration:4s;animation-iteration-count:infinite;animation-name:progress;animation-timing-function:linear;transform:translateZ(0)}.monaco-progress-container.infinite.infinite-long-running .progress-bit{animation-timing-function:steps(100)}@keyframes progress{0%{transform:translateX(0) scaleX(1)}50%{transform:translateX(2500%) scaleX(3)}to{transform:translateX(4900%) scaleX(1)}}",""]),t.A=o},2362:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,':root{--sash-size:4px}.monaco-sash{position:absolute;touch-action:none;z-index:35}.monaco-sash.disabled{pointer-events:none}.monaco-sash.mac.vertical{cursor:col-resize}.monaco-sash.vertical.minimum{cursor:e-resize}.monaco-sash.vertical.maximum{cursor:w-resize}.monaco-sash.mac.horizontal{cursor:row-resize}.monaco-sash.horizontal.minimum{cursor:s-resize}.monaco-sash.horizontal.maximum{cursor:n-resize}.monaco-sash.disabled{cursor:default!important;pointer-events:none!important}.monaco-sash.vertical{cursor:ew-resize;height:100%;top:0;width:var(--sash-size)}.monaco-sash.horizontal{cursor:ns-resize;height:var(--sash-size);left:0;width:100%}.monaco-sash:not(.disabled)>.orthogonal-drag-handle{content:" ";cursor:all-scroll;display:block;height:calc(var(--sash-size)*2);position:absolute;width:calc(var(--sash-size)*2);z-index:100}.monaco-sash.horizontal.orthogonal-edge-north:not(.disabled)>.orthogonal-drag-handle.start,.monaco-sash.horizontal.orthogonal-edge-south:not(.disabled)>.orthogonal-drag-handle.end{cursor:nwse-resize}.monaco-sash.horizontal.orthogonal-edge-north:not(.disabled)>.orthogonal-drag-handle.end,.monaco-sash.horizontal.orthogonal-edge-south:not(.disabled)>.orthogonal-drag-handle.start{cursor:nesw-resize}.monaco-sash.vertical>.orthogonal-drag-handle.start{left:calc(var(--sash-size)*-.5);top:calc(var(--sash-size)*-1)}.monaco-sash.vertical>.orthogonal-drag-handle.end{bottom:calc(var(--sash-size)*-1);left:calc(var(--sash-size)*-.5)}.monaco-sash.horizontal>.orthogonal-drag-handle.start{left:calc(var(--sash-size)*-1);top:calc(var(--sash-size)*-.5)}.monaco-sash.horizontal>.orthogonal-drag-handle.end{right:calc(var(--sash-size)*-1);top:calc(var(--sash-size)*-.5)}.monaco-sash:before{background:transparent;content:"";height:100%;pointer-events:none;position:absolute;transition:background-color .1s ease-out;width:100%}.monaco-sash.vertical:before{left:calc(50% - var(--sash-hover-size)/2);width:var(--sash-hover-size)}.monaco-sash.horizontal:before{height:var(--sash-hover-size);top:calc(50% - var(--sash-hover-size)/2)}.pointer-events-disabled{pointer-events:none!important}.monaco-sash.debug{background:cyan}.monaco-sash.debug.disabled{background:rgba(0,255,255,.2)}.monaco-sash.debug:not(.disabled)>.orthogonal-drag-handle{background:red}',""]),t.A=o},9160:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.monaco-scrollable-element>.visible{background:transparent;opacity:1;transition:opacity .1s linear}.monaco-scrollable-element>.invisible{opacity:0;pointer-events:none}.monaco-scrollable-element>.invisible.fade{transition:opacity .8s linear}.monaco-scrollable-element>.shadow{display:none;position:absolute}.monaco-scrollable-element>.shadow.top{display:block;height:3px;left:3px;top:0;width:100%}.monaco-scrollable-element>.shadow.left{display:block;height:100%;left:0;top:3px;width:3px}.monaco-scrollable-element>.shadow.top-left-corner{display:block;height:3px;left:0;top:0;width:3px}",""]),t.A=o},710:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,'.monaco-split-view2{height:100%;position:relative;width:100%}.monaco-split-view2>.sash-container{height:100%;pointer-events:none;position:absolute;width:100%}.monaco-split-view2>.sash-container>.monaco-sash{pointer-events:auto}.monaco-split-view2>.monaco-scrollable-element{height:100%;width:100%}.monaco-split-view2>.monaco-scrollable-element>.split-view-container{height:100%;position:relative;white-space:nowrap;width:100%}.monaco-split-view2>.monaco-scrollable-element>.split-view-container>.split-view-view{position:absolute;white-space:normal}.monaco-split-view2>.monaco-scrollable-element>.split-view-container>.split-view-view:not(.visible){display:none}.monaco-split-view2.vertical>.monaco-scrollable-element>.split-view-container>.split-view-view{width:100%}.monaco-split-view2.horizontal>.monaco-scrollable-element>.split-view-container>.split-view-view{height:100%}.monaco-split-view2.separator-border>.monaco-scrollable-element>.split-view-container>.split-view-view:not(:first-child):before{background-color:var(--separator-border);content:" ";left:0;pointer-events:none;position:absolute;top:0;z-index:5}.monaco-split-view2.separator-border.horizontal>.monaco-scrollable-element>.split-view-container>.split-view-view:not(:first-child):before{height:100%;width:1px}.monaco-split-view2.separator-border.vertical>.monaco-scrollable-element>.split-view-container>.split-view-view:not(:first-child):before{height:1px;width:100%}',""]),t.A=o},8110:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,'.monaco-table{display:flex;flex-direction:column;height:100%;position:relative;white-space:nowrap;width:100%}.monaco-table>.monaco-split-view2{border-bottom:1px solid transparent}.monaco-table>.monaco-list{flex:1}.monaco-table-tr{display:flex;height:100%}.monaco-table-th{font-weight:700;height:100%;overflow:hidden;text-overflow:ellipsis;width:100%}.monaco-table-td,.monaco-table-th{box-sizing:border-box;flex-shrink:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.monaco-table>.monaco-split-view2 .monaco-sash.vertical:before{border-left:1px solid transparent;content:"";left:calc(var(--sash-size)/2);position:absolute;width:0}.monaco-table>.monaco-split-view2,.monaco-table>.monaco-split-view2 .monaco-sash.vertical:before{transition:border-color .2s ease-out}',""]),t.A=o},1368:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-custom-toggle{border:1px solid transparent;border-radius:3px;box-sizing:border-box;cursor:pointer;float:left;height:20px;margin-left:2px;overflow:hidden;padding:1px;-moz-user-select:none;user-select:none;-webkit-user-select:none;-ms-user-select:none;width:20px}.monaco-custom-toggle:hover{background-color:var(--vscode-inputOption-hoverBackground)}.hc-black .monaco-custom-toggle:hover,.hc-light .monaco-custom-toggle:hover{border:1px dashed var(--vscode-focusBorder)}.hc-black .monaco-custom-toggle,.hc-black .monaco-custom-toggle:hover,.hc-light .monaco-custom-toggle,.hc-light .monaco-custom-toggle:hover{background:none}.monaco-custom-toggle.monaco-checkbox{background-size:16px!important;border:1px solid transparent;border-radius:3px;height:18px;margin-left:0;margin-right:9px;opacity:1;padding:0;width:18px}.monaco-custom-toggle.monaco-checkbox:not(.checked):before{visibility:hidden}",""]),t.A=o},8479:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-tl-row{align-items:center;display:flex;height:100%;position:relative}.monaco-tl-indent{height:100%;left:16px;pointer-events:none;position:absolute;top:0}.hide-arrows .monaco-tl-indent{left:12px}.monaco-tl-indent>.indent-guide{border-left:1px solid transparent;box-sizing:border-box;display:inline-block;height:100%;transition:border-color .1s linear}.monaco-tl-contents,.monaco-tl-twistie{height:100%}.monaco-tl-twistie{align-items:center;display:flex!important;flex-shrink:0;font-size:10px;justify-content:center;padding-right:6px;text-align:right;transform:translateX(3px);width:16px}.monaco-tl-contents{flex:1;overflow:hidden}.monaco-tl-twistie:before{border-radius:20px}.monaco-tl-twistie.collapsed:before{transform:rotate(-90deg)}.monaco-tl-twistie.codicon-tree-item-loading:before{animation:codicon-spin 1.25s steps(30) infinite}.monaco-tree-type-filter{display:flex;margin:0 6px;max-width:200px;padding:3px;position:absolute;top:0;transition:top .3s;z-index:100}.monaco-tree-type-filter.disabled{top:-40px}.monaco-tree-type-filter-grab{align-items:center;cursor:grab;display:flex!important;justify-content:center;margin-right:2px}.monaco-tree-type-filter-grab.grabbing{cursor:grabbing}.monaco-tree-type-filter-input{flex:1}.monaco-tree-type-filter-input .monaco-inputbox{height:23px}.monaco-tree-type-filter-input .monaco-inputbox>.ibwrapper>.input,.monaco-tree-type-filter-input .monaco-inputbox>.ibwrapper>.mirror{padding:2px 4px}.monaco-tree-type-filter-input .monaco-findInput>.controls{top:2px}.monaco-tree-type-filter-actionbar{margin-left:4px}.monaco-tree-type-filter-actionbar .monaco-action-bar .action-label{padding:2px}",""]),t.A=o},4697:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,'.quick-input-widget{-webkit-app-region:no-drag;left:50%;margin-left:-300px;position:absolute;width:600px;z-index:2550}.quick-input-titlebar{align-items:center;display:flex}.quick-input-left-action-bar{display:flex;flex:1;margin-left:4px}.quick-input-title{overflow:hidden;padding:3px 0;text-align:center;text-overflow:ellipsis}.quick-input-right-action-bar{display:flex;flex:1;margin-right:4px}.quick-input-right-action-bar>.actions-container{justify-content:flex-end}.quick-input-titlebar .monaco-action-bar .action-label.codicon{background-position:50%;background-repeat:no-repeat;padding:2px}.quick-input-description{margin:6px}.quick-input-header .quick-input-description{margin:4px 2px}.quick-input-header{display:flex;margin-bottom:-2px;padding:6px 6px 0}.quick-input-widget.hidden-input .quick-input-header{margin-bottom:0;padding:0}.quick-input-and-message{display:flex;flex-direction:column;flex-grow:1;min-width:0;position:relative}.quick-input-check-all{align-self:center;margin:0}.quick-input-filter{display:flex;flex-grow:1;position:relative}.quick-input-box{flex-grow:1}.quick-input-widget.show-checkboxes .quick-input-box,.quick-input-widget.show-checkboxes .quick-input-message{margin-left:5px}.quick-input-visible-count{left:-10000px;position:absolute}.quick-input-count{align-items:center;align-self:center;display:flex;position:absolute;right:4px}.quick-input-count .monaco-count-badge{border-radius:2px;line-height:normal;min-height:auto;padding:2px 4px;vertical-align:middle}.quick-input-action{margin-left:6px}.quick-input-action .monaco-text-button{align-items:center;display:flex;font-size:11px;height:27.5px;padding:0 6px}.quick-input-message{margin-top:-1px;overflow-wrap:break-word;padding:5px}.quick-input-message>.codicon{margin:0 .2em;vertical-align:text-bottom}.quick-input-progress.monaco-progress-container{position:relative}.quick-input-progress.monaco-progress-container,.quick-input-progress.monaco-progress-container .progress-bit{height:2px}.quick-input-list{line-height:22px;margin-top:6px;padding:0 1px 1px}.quick-input-widget.hidden-input .quick-input-list{margin-top:0}.quick-input-list .monaco-list{max-height:440px;overflow:hidden}.quick-input-list .quick-input-list-entry{box-sizing:border-box;display:flex;height:100%;overflow:hidden;padding:0 6px}.quick-input-list .quick-input-list-entry.quick-input-list-separator-border{border-top-style:solid;border-top-width:1px}.quick-input-list .monaco-list-row[data-index="0"] .quick-input-list-entry.quick-input-list-separator-border{border-top-style:none}.quick-input-list .quick-input-list-label{display:flex;flex:1;height:100%;overflow:hidden}.quick-input-list .quick-input-list-checkbox{align-self:center;margin:0}.quick-input-list .quick-input-list-rows{display:flex;flex:1;flex-direction:column;height:100%;margin-left:5px;overflow:hidden;text-overflow:ellipsis}.quick-input-widget.show-checkboxes .quick-input-list .quick-input-list-rows{margin-left:10px}.quick-input-widget .quick-input-list .quick-input-list-checkbox{display:none}.quick-input-widget.show-checkboxes .quick-input-list .quick-input-list-checkbox{display:inline}.quick-input-list .quick-input-list-rows>.quick-input-list-row{align-items:center;display:flex}.quick-input-list .quick-input-list-rows>.quick-input-list-row .monaco-icon-label,.quick-input-list .quick-input-list-rows>.quick-input-list-row .monaco-icon-label .monaco-icon-label-container>.monaco-icon-name-container{flex:1}.quick-input-list .quick-input-list-rows>.quick-input-list-row .codicon[class*=codicon-]{vertical-align:text-bottom}.quick-input-list .quick-input-list-rows .monaco-highlighted-label span{opacity:1}.quick-input-list .quick-input-list-entry .quick-input-list-entry-keybinding{margin-right:8px}.quick-input-list .quick-input-list-label-meta{line-height:normal;opacity:.7;overflow:hidden;text-overflow:ellipsis}.quick-input-list .monaco-highlighted-label .highlight{font-weight:700}.quick-input-list .quick-input-list-entry .quick-input-list-separator{margin-right:8px}.quick-input-list .quick-input-list-entry-action-bar{display:flex;flex:0;overflow:visible}.quick-input-list .quick-input-list-entry-action-bar .action-label{display:none}.quick-input-list .quick-input-list-entry-action-bar .action-label.codicon{margin-right:4px;padding:0 2px 2px}.quick-input-list .quick-input-list-entry-action-bar{margin-right:4px;margin-top:1px}.quick-input-list .monaco-list-row.focused .quick-input-list-entry-action-bar .action-label,.quick-input-list .quick-input-list-entry .quick-input-list-entry-action-bar .action-label.always-visible,.quick-input-list .quick-input-list-entry:hover .quick-input-list-entry-action-bar .action-label{display:flex}.quick-input-list .monaco-list-row.focused .monaco-keybinding-key,.quick-input-list .monaco-list-row.focused .quick-input-list-entry .quick-input-list-separator{color:inherit}.quick-input-list .monaco-list-row.focused .monaco-keybinding-key{background:none}',""]),t.A=o},8551:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .inputarea{background-color:transparent;border:none;color:transparent;margin:0;min-height:0;min-width:0;outline:none!important;overflow:hidden;padding:0;position:absolute;resize:none}.monaco-editor .inputarea.ime-input{z-index:10}",""]),t.A=o},2335:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .blockDecorations-container{position:absolute;top:0}.monaco-editor .blockDecorations-block{box-sizing:border-box;position:absolute}",""]),t.A=o},8001:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .margin-view-overlays .current-line,.monaco-editor .view-overlays .current-line{box-sizing:border-box;display:block;left:0;position:absolute;top:0}.monaco-editor .margin-view-overlays .current-line.current-line-margin.current-line-margin-both{border-right:0}",""]),t.A=o},2577:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .lines-content .cdr{position:absolute}",""]),t.A=o},6477:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .glyph-margin{position:absolute;top:0}.monaco-editor .margin-view-overlays .cgmr{align-items:center;display:flex;justify-content:center;position:absolute}",""]),t.A=o},7021:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .lines-content .core-guide{box-sizing:border-box;position:absolute}",""]),t.A=o},8101:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .margin-view-overlays .line-numbers{box-sizing:border-box;cursor:default;display:inline-block;font-variant-numeric:tabular-nums;height:100%;position:absolute;text-align:right;vertical-align:middle}.monaco-editor .relative-current-line-number{display:inline-block;text-align:left;width:100%}.monaco-editor .margin-view-overlays .line-numbers.lh-odd{margin-top:1px}",""]),t.A=o},6888:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".mtkcontrol{background:#960000!important;color:#fff!important}.monaco-editor.no-user-select .lines-content,.monaco-editor.no-user-select .view-line,.monaco-editor.no-user-select .view-lines{-moz-user-select:none;user-select:none;-webkit-user-select:none;-ms-user-select:none}.monaco-editor.enable-user-select{-moz-user-select:initial;user-select:auto;-webkit-user-select:initial;-ms-user-select:initial}.monaco-editor .view-lines{white-space:nowrap}.monaco-editor .view-line{position:absolute;width:100%}.monaco-editor .mtkz{display:inline-block}",""]),t.A=o},6651:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .lines-decorations{background:#fff;position:absolute;top:0}.monaco-editor .margin-view-overlays .cldr{height:100%;position:absolute}",""]),t.A=o},77:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .margin-view-overlays .cmdr{height:100%;left:0;position:absolute;width:100%}",""]),t.A=o},8633:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .minimap.slider-mouseover .minimap-slider{opacity:0;transition:opacity .1s linear}.monaco-editor .minimap.slider-mouseover .minimap-slider.active,.monaco-editor .minimap.slider-mouseover:hover .minimap-slider{opacity:1}.monaco-editor .minimap-shadow-hidden{position:absolute;width:0}.monaco-editor .minimap-shadow-visible{left:-6px;position:absolute;width:6px}.monaco-editor.no-minimap-shadow .minimap-shadow-visible{left:-1px;position:absolute;width:1px}.minimap.autohide{opacity:0;transition:opacity .5s}.minimap.autohide:hover{opacity:1}",""]),t.A=o},2433:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .overlayWidgets{left:0;position:absolute;top:0}",""]),t.A=o},3985:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .view-ruler{position:absolute;top:0}",""]),t.A=o},4713:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .scroll-decoration{height:6px;left:0;position:absolute;top:0}",""]),t.A=o},9865:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .lines-content .cslr{position:absolute}.monaco-editor\t\t\t.top-left-radius{border-top-left-radius:3px}.monaco-editor\t\t\t.bottom-left-radius{border-bottom-left-radius:3px}.monaco-editor\t\t\t.top-right-radius{border-top-right-radius:3px}.monaco-editor\t\t\t.bottom-right-radius{border-bottom-right-radius:3px}.monaco-editor.hc-black .top-left-radius{border-top-left-radius:0}.monaco-editor.hc-black .bottom-left-radius{border-bottom-left-radius:0}.monaco-editor.hc-black .top-right-radius{border-top-right-radius:0}.monaco-editor.hc-black .bottom-right-radius{border-bottom-right-radius:0}.monaco-editor.hc-light .top-left-radius{border-top-left-radius:0}.monaco-editor.hc-light .bottom-left-radius{border-bottom-left-radius:0}.monaco-editor.hc-light .top-right-radius{border-top-right-radius:0}.monaco-editor.hc-light .bottom-right-radius{border-bottom-right-radius:0}",""]),t.A=o},2269:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .cursors-layer{position:absolute;top:0}.monaco-editor .cursors-layer>.cursor{overflow:hidden;position:absolute}.monaco-editor .cursors-layer.cursor-smooth-caret-animation>.cursor{transition:all 80ms}.monaco-editor .cursors-layer.cursor-block-outline-style>.cursor{background:transparent!important;border-style:solid;border-width:1px;box-sizing:border-box}.monaco-editor .cursors-layer.cursor-underline-style>.cursor{background:transparent!important;border-bottom-style:solid;border-bottom-width:2px;box-sizing:border-box}.monaco-editor .cursors-layer.cursor-underline-thin-style>.cursor{background:transparent!important;border-bottom-style:solid;border-bottom-width:1px;box-sizing:border-box}@keyframes monaco-cursor-smooth{0%,20%{opacity:1}60%,to{opacity:0}}@keyframes monaco-cursor-phase{0%,20%{opacity:1}90%,to{opacity:0}}@keyframes monaco-cursor-expand{0%,20%{transform:scaleY(1)}80%,to{transform:scaleY(0)}}.cursor-smooth{animation:monaco-cursor-smooth .5s ease-in-out 0s 20 alternate}.cursor-phase{animation:monaco-cursor-phase .5s ease-in-out 0s 20 alternate}.cursor-expand>.cursor{animation:monaco-cursor-expand .5s ease-in-out 0s 20 alternate}",""]),t.A=o},208:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-diff-editor .diffOverview{z-index:9}.monaco-diff-editor .diffOverview .diffViewport{z-index:10}.monaco-diff-editor.vs\t\t\t.diffOverview{background:rgba(0,0,0,.03)}.monaco-diff-editor.vs-dark\t\t.diffOverview{background:hsla(0,0%,100%,.01)}.monaco-scrollable-element.modified-in-monaco-diff-editor.vs\t\t.scrollbar,.monaco-scrollable-element.modified-in-monaco-diff-editor.vs-dark\t.scrollbar{background:transparent}.monaco-scrollable-element.modified-in-monaco-diff-editor.hc-black\t.scrollbar,.monaco-scrollable-element.modified-in-monaco-diff-editor.hc-light\t.scrollbar{background:none}.monaco-scrollable-element.modified-in-monaco-diff-editor .slider{z-index:10}.modified-in-monaco-diff-editor\t\t\t\t.slider.active{background:hsla(0,0%,67%,.4)}.modified-in-monaco-diff-editor.hc-black\t.slider.active,.modified-in-monaco-diff-editor.hc-light\t.slider.active{background:none}.monaco-diff-editor .delete-sign,.monaco-diff-editor .insert-sign,.monaco-editor .delete-sign,.monaco-editor .insert-sign{align-items:center;display:flex!important;font-size:11px!important;opacity:.7!important}.monaco-diff-editor.hc-black .delete-sign,.monaco-diff-editor.hc-black .insert-sign,.monaco-diff-editor.hc-light .delete-sign,.monaco-diff-editor.hc-light .insert-sign,.monaco-editor.hc-black .delete-sign,.monaco-editor.hc-black .insert-sign,.monaco-editor.hc-light .delete-sign,.monaco-editor.hc-light .insert-sign{opacity:1}.monaco-editor .inline-added-margin-view-zone,.monaco-editor .inline-deleted-margin-view-zone{text-align:right}.monaco-editor .arrow-revert-change{position:absolute;z-index:10}.monaco-editor .arrow-revert-change:hover{cursor:pointer}.monaco-editor .view-zones .view-lines .view-line span{display:inline-block}.monaco-editor .margin-view-zones .lightbulb-glyph:hover{cursor:pointer}",""]),t.A=o},8407:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-diff-editor .diff-review-line-number{display:inline-block;text-align:right}.monaco-diff-editor .diff-review{position:absolute;-moz-user-select:none;user-select:none;-webkit-user-select:none;-ms-user-select:none}.monaco-diff-editor .diff-review-summary{padding-left:10px}.monaco-diff-editor .diff-review-shadow{position:absolute}.monaco-diff-editor .diff-review-row{white-space:pre}.monaco-diff-editor .diff-review-table{display:table;min-width:100%}.monaco-diff-editor .diff-review-row{display:table-row;width:100%}.monaco-diff-editor .diff-review-spacer{display:inline-block;vertical-align:middle;width:10px}.monaco-diff-editor .diff-review-spacer>.codicon{font-size:9px!important}.monaco-diff-editor .diff-review-actions{display:inline-block;position:absolute;right:10px;top:2px}.monaco-diff-editor .diff-review-actions .action-label{height:16px;margin:2px 0;width:16px}",""]),t.A=o},4029:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,"::-ms-clear{display:none}.monaco-editor .editor-widget input{color:inherit}.monaco-editor{-webkit-text-size-adjust:100%;overflow:visible;position:relative}.monaco-editor .overflow-guard{overflow:hidden;position:relative}.monaco-editor .view-overlays{position:absolute;top:0}",""]),t.A=o},5031:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .selection-anchor{background-color:#007acc;width:2px!important}",""]),t.A=o},1713:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .bracket-match{box-sizing:border-box}",""]),t.A=o},4629:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .contentWidgets .codicon-light-bulb,.monaco-editor .contentWidgets .codicon-lightbulb-autofix{align-items:center;display:flex;justify-content:center}.monaco-editor .contentWidgets .codicon-light-bulb:hover,.monaco-editor .contentWidgets .codicon-lightbulb-autofix:hover{cursor:pointer}",""]),t.A=o},511:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,'.codeActionMenuWidget{background-color:var(--vscode-menu-background);border-color:none;border-radius:5px;border-width:0;box-shadow:0 2px 8px rgb(0,0,0,16%);color:var(--vscode-menu-foreground);display:block;font-size:13px;min-width:160px;overflow:auto;padding:8px 0;width:100%;z-index:40}.codeActionMenuWidget .monaco-list:not(.element-focused):focus:before{content:"";height:100%;left:0;outline:0 solid!important;outline-offset:0!important;outline-style:none!important;outline-width:0!important;pointer-events:none;position:absolute;top:0;width:100%;z-index:5}.codeActionMenuWidget .monaco-list{border:0!important;-moz-user-select:none;user-select:none;-webkit-user-select:none;-ms-user-select:none}.codeActionMenuWidget .monaco-list .monaco-scrollable-element .monaco-list-rows{height:100%!important}.codeActionMenuWidget .monaco-list .monaco-scrollable-element{overflow:visible}.codeActionMenuWidget .monaco-list .monaco-list-row:not(.separator){background-position:2px 2px;background-repeat:no-repeat;-mox-box-sizing:border-box;box-sizing:border-box;cursor:pointer;display:flex;padding:0 26px;touch-action:none;white-space:nowrap;width:100%}.codeActionMenuWidget .monaco-list .monaco-list-row:hover:not(.option-disabled),.codeActionMenuWidget .monaco-list .moncao-list-row.focused:not(.option-disabled){background-color:var(--vscode-menu-selectionBackground)!important;color:var(--vscode-menu-selectionForeground)!important}.codeActionMenuWidget .monaco-list .option-disabled,.codeActionMenuWidget .monaco-list .option-disabled .focused{-webkit-touch-callout:none;color:var(--vscode-disabledForeground)!important;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.codeActionMenuWidget .monaco-list .separator{background-position:2px 2px;background-repeat:no-repeat;border-bottom:1px solid var(--vscode-menu-separatorBackground);border-radius:0;-mox-box-sizing:border-box;box-sizing:border-box;cursor:pointer;display:flex;font-size:inherit;height:0!important;margin:5px 0!important;opacity:1;padding-top:0!important;touch-action:none;white-space:nowrap;width:100%}',""]),t.A=o},8907:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .codelens-decoration{color:var(--vscode-editorCodeLens-foreground);display:inline-block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.monaco-editor .codelens-decoration>a,.monaco-editor .codelens-decoration>span{-moz-user-select:none;user-select:none;-webkit-user-select:none;-ms-user-select:none;vertical-align:sub;white-space:nowrap}.monaco-editor .codelens-decoration>a{text-decoration:none}.monaco-editor .codelens-decoration>a:hover{cursor:pointer}.monaco-editor .codelens-decoration>a:hover,.monaco-editor .codelens-decoration>a:hover .codicon{color:var(--vscode-editorLink-activeForeground)!important}.monaco-editor .codelens-decoration .codicon{color:currentColor!important;color:var(--vscode-editorCodeLens-foreground);vertical-align:middle}.monaco-editor .codelens-decoration>a:hover .codicon:before{cursor:pointer}@keyframes fadein{0%{opacity:0;visibility:visible}to{opacity:1}}.monaco-editor .codelens-decoration.fadein{animation:fadein .1s linear}",""]),t.A=o},3365:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,'.colorpicker-widget{height:190px;-moz-user-select:none;user-select:none;-webkit-user-select:none;-ms-user-select:none}.colorpicker-color-decoration,.hc-light .colorpicker-color-decoration{border:.1em solid #000;box-sizing:border-box;cursor:pointer;display:inline-block;height:.8em;line-height:.8em;margin:.1em .2em 0;width:.8em}.hc-black .colorpicker-color-decoration,.vs-dark .colorpicker-color-decoration{border:.1em solid #eee}.colorpicker-header{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTZEaa/1AAAAHUlEQVQYV2PYvXu3JAi7uLiAMaYAjAGTQBPYLQkAa/0Zef3qRswAAAAASUVORK5CYII=");background-size:9px 9px;display:flex;height:24px;image-rendering:pixelated;position:relative}.colorpicker-header .picked-color{align-items:center;color:#fff;cursor:pointer;display:flex;flex:1;justify-content:center;line-height:24px;width:216px}.colorpicker-header .picked-color .codicon{color:inherit;font-size:14px;left:8px;position:absolute}.colorpicker-header .picked-color.light{color:#000}.colorpicker-header .original-color{cursor:pointer;width:74px;z-index:inherit}.colorpicker-body{display:flex;padding:8px;position:relative}.colorpicker-body .saturation-wrap{flex:1;height:150px;min-width:220px;overflow:hidden;position:relative}.colorpicker-body .saturation-box{height:150px;position:absolute}.colorpicker-body .saturation-selection{border:1px solid #fff;border-radius:100%;box-shadow:0 0 2px rgba(0,0,0,.8);height:9px;margin:-5px 0 0 -5px;position:absolute;width:9px}.colorpicker-body .strip{height:150px;width:25px}.colorpicker-body .hue-strip{background:linear-gradient(180deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red);cursor:grab;margin-left:8px;position:relative}.colorpicker-body .opacity-strip{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAAECAYAAACp8Z5+AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAZdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjAuMTZEaa/1AAAAHUlEQVQYV2PYvXu3JAi7uLiAMaYAjAGTQBPYLQkAa/0Zef3qRswAAAAASUVORK5CYII=");background-size:9px 9px;cursor:grab;image-rendering:pixelated;margin-left:8px;position:relative}.colorpicker-body .strip.grabbing{cursor:grabbing}.colorpicker-body .slider{border:1px solid hsla(0,0%,100%,.71);box-shadow:0 0 1px rgba(0,0,0,.85);box-sizing:border-box;height:4px;left:-2px;position:absolute;top:0;width:calc(100% + 4px)}.colorpicker-body .strip .overlay{height:150px;pointer-events:none}',""]),t.A=o},2239:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .find-widget{box-sizing:border-box;height:33px;line-height:19px;overflow:hidden;padding:0 4px;position:absolute;transform:translateY(calc(-100% - 10px));transition:transform .2s linear;z-index:35}.monaco-workbench.reduce-motion .monaco-editor .find-widget{transition:transform 0ms linear}.monaco-editor .find-widget textarea{margin:0}.monaco-editor .find-widget.hiddenEditor{display:none}.monaco-editor .find-widget.replaceToggled>.replace-part{display:flex}.monaco-editor .find-widget.visible{transform:translateY(0)}.monaco-editor .find-widget .monaco-inputbox.synthetic-focus{outline:1px solid -webkit-focus-ring-color;outline-offset:-1px}.monaco-editor .find-widget .monaco-inputbox .input{background-color:transparent;min-height:0}.monaco-editor .find-widget .monaco-findInput .input{font-size:13px}.monaco-editor .find-widget>.find-part,.monaco-editor .find-widget>.replace-part{display:flex;font-size:12px;margin:4px 0 0 17px}.monaco-editor .find-widget>.find-part .monaco-inputbox,.monaco-editor .find-widget>.replace-part .monaco-inputbox{min-height:25px}.monaco-editor .find-widget>.replace-part .monaco-inputbox>.ibwrapper>.mirror{padding-right:22px}.monaco-editor .find-widget>.find-part .monaco-inputbox>.ibwrapper>.input,.monaco-editor .find-widget>.find-part .monaco-inputbox>.ibwrapper>.mirror,.monaco-editor .find-widget>.replace-part .monaco-inputbox>.ibwrapper>.input,.monaco-editor .find-widget>.replace-part .monaco-inputbox>.ibwrapper>.mirror{padding-bottom:2px;padding-top:2px}.monaco-editor .find-widget>.find-part .find-actions,.monaco-editor .find-widget>.replace-part .replace-actions{align-items:center;display:flex;height:25px}.monaco-editor .find-widget .monaco-findInput{display:flex;flex:1;vertical-align:middle}.monaco-editor .find-widget .monaco-findInput .monaco-scrollable-element{width:100%}.monaco-editor .find-widget .monaco-findInput .monaco-scrollable-element .scrollbar.vertical{opacity:0}.monaco-editor .find-widget .matchesCount{box-sizing:border-box;display:flex;flex:initial;height:25px;line-height:23px;margin:0 0 0 3px;padding:2px 0 0 2px;text-align:center;vertical-align:middle}.monaco-editor .find-widget .button{align-items:center;background-position:50%;background-repeat:no-repeat;border-radius:5px;cursor:pointer;display:flex;flex:initial;height:16px;justify-content:center;margin-left:3px;padding:3px;width:16px}.monaco-editor .find-widget .codicon-find-selection{border-radius:5px;height:22px;padding:3px;width:22px}.monaco-editor .find-widget .button.left{margin-left:0;margin-right:3px}.monaco-editor .find-widget .button.wide{padding:1px 6px;top:-1px;width:auto}.monaco-editor .find-widget .button.toggle{border-radius:0;box-sizing:border-box;height:100%;left:3px;position:absolute;top:0;width:18px}.monaco-editor .find-widget .button.toggle.disabled{display:none}.monaco-editor .find-widget .disabled{color:var(--vscode-disabledForeground);cursor:default}.monaco-editor .find-widget>.replace-part{display:none}.monaco-editor .find-widget>.replace-part>.monaco-findInput{display:flex;flex:auto;flex-grow:0;flex-shrink:0;position:relative;vertical-align:middle}.monaco-editor .find-widget>.replace-part>.monaco-findInput>.controls{position:absolute;right:2px;top:3px}.monaco-editor .find-widget.reduced-find-widget .matchesCount{display:none}.monaco-editor .find-widget.narrow-find-widget{max-width:257px!important}.monaco-editor .find-widget.collapsed-find-widget{max-width:170px!important}.monaco-editor .find-widget.collapsed-find-widget .button.next,.monaco-editor .find-widget.collapsed-find-widget .button.previous,.monaco-editor .find-widget.collapsed-find-widget .button.replace,.monaco-editor .find-widget.collapsed-find-widget .button.replace-all,.monaco-editor .find-widget.collapsed-find-widget>.find-part .monaco-findInput .controls{display:none}.monaco-editor .findMatch{animation-duration:0;animation-name:inherit!important}.monaco-editor .find-widget .monaco-sash{left:0!important}.monaco-editor.hc-black .find-widget .button:before{left:2px;position:relative;top:1px}",""]),t.A=o},7121:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,'.monaco-editor .margin-view-overlays .codicon-folding-collapsed,.monaco-editor .margin-view-overlays .codicon-folding-expanded,.monaco-editor .margin-view-overlays .codicon-folding-manual-collapsed,.monaco-editor .margin-view-overlays .codicon-folding-manual-expanded{align-items:center;cursor:pointer;display:flex;font-size:140%;justify-content:center;margin-left:2px;opacity:0;transition:opacity .5s}.monaco-editor .margin-view-overlays .codicon.alwaysShowFoldIcons,.monaco-editor .margin-view-overlays .codicon.codicon-folding-collapsed,.monaco-editor .margin-view-overlays .codicon.codicon-folding-manual-collapsed,.monaco-editor .margin-view-overlays:hover .codicon{opacity:1}.monaco-editor .inline-folded:after{color:grey;content:"⋯";cursor:pointer;display:inline;line-height:1em;margin:.1em .2em 0}',""]),t.A=o},8120:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,'.monaco-editor .peekview-widget .head .peekview-title .severity-icon{display:inline-block;margin-right:4px;vertical-align:text-top}.monaco-editor .marker-widget{text-overflow:ellipsis;white-space:nowrap}.monaco-editor .marker-widget>.stale{font-style:italic;opacity:.6}.monaco-editor .marker-widget .title{display:inline-block;padding-right:5px}.monaco-editor .marker-widget .descriptioncontainer{padding:8px 12px 0 20px;position:absolute;-moz-user-select:text;user-select:text;-webkit-user-select:text;-ms-user-select:text;white-space:pre}.monaco-editor .marker-widget .descriptioncontainer .message{display:flex;flex-direction:column}.monaco-editor .marker-widget .descriptioncontainer .message .details{padding-left:6px}.monaco-editor .marker-widget .descriptioncontainer .message .source,.monaco-editor .marker-widget .descriptioncontainer .message span.code{opacity:.6}.monaco-editor .marker-widget .descriptioncontainer .message a.code-link{color:inherit;opacity:.6}.monaco-editor .marker-widget .descriptioncontainer .message a.code-link:before{content:"("}.monaco-editor .marker-widget .descriptioncontainer .message a.code-link:after{content:")"}.monaco-editor .marker-widget .descriptioncontainer .message a.code-link>span{border-bottom:1px solid transparent;color:var(--vscode-textLink-foreground);color:var(--vscode-textLink-activeForeground);text-decoration:underline;text-underline-position:under}.monaco-editor .marker-widget .descriptioncontainer .filename{cursor:pointer}',""]),t.A=o},2939:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .goto-definition-link{cursor:pointer;text-decoration:underline}",""]),t.A=o},6494:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .zone-widget .zone-widget-container.reference-zone-widget{border-bottom-width:1px;border-top-width:1px}.monaco-editor .reference-zone-widget .inline{display:inline-block;vertical-align:top}.monaco-editor .reference-zone-widget .messages{height:100%;padding:3em 0;text-align:center;width:100%}.monaco-editor .reference-zone-widget .ref-tree{background-color:var(--vscode-peekViewResult-background);color:var(--vscode-peekViewResult-lineForeground);line-height:23px}.monaco-editor .reference-zone-widget .ref-tree .reference{overflow:hidden;text-overflow:ellipsis}.monaco-editor .reference-zone-widget .ref-tree .reference-file{color:var(--vscode-peekViewResult-fileForeground);display:inline-flex;height:100%;width:100%}.monaco-editor .reference-zone-widget .ref-tree .monaco-list:focus .selected .reference-file{color:inherit!important}.monaco-editor .reference-zone-widget .ref-tree .monaco-list:focus .monaco-list-rows>.monaco-list-row.selected:not(.highlighted){background-color:var(--vscode-peekViewResult-selectionBackground);color:var(--vscode-peekViewResult-selectionForeground)!important}.monaco-editor .reference-zone-widget .ref-tree .reference-file .count{margin-left:auto;margin-right:12px}.monaco-editor .reference-zone-widget .ref-tree .referenceMatch .highlight{background-color:var(--vscode-peekViewResult-matchHighlightBackground)}.monaco-editor .reference-zone-widget .preview .reference-decoration{background-color:var(--vscode-peekViewEditor-matchHighlightBackground);border:2px solid var(--vscode-peekViewEditor-matchHighlightBorder);box-sizing:border-box}.monaco-editor .reference-zone-widget .preview .monaco-editor .inputarea.ime-input,.monaco-editor .reference-zone-widget .preview .monaco-editor .monaco-editor-background{background-color:var(--vscode-peekViewEditor-background)}.monaco-editor .reference-zone-widget .preview .monaco-editor .margin{background-color:var(--vscode-peekViewEditorGutter-background)}.monaco-editor.hc-black .reference-zone-widget .ref-tree .reference-file,.monaco-editor.hc-light .reference-zone-widget .ref-tree .reference-file{font-weight:700}.monaco-editor.hc-black .reference-zone-widget .ref-tree .referenceMatch .highlight,.monaco-editor.hc-light .reference-zone-widget .ref-tree .referenceMatch .highlight{border:1px dotted var(--vscode-contrastActiveBorder,transparent);box-sizing:border-box}",""]),t.A=o},8317:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .detected-link,.monaco-editor .detected-link-active{text-decoration:underline;text-underline-position:under}.monaco-editor .detected-link-active{cursor:pointer}",""]),t.A=o},2541:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .monaco-editor-overlaymessage{padding-bottom:8px;z-index:10000}.monaco-editor .monaco-editor-overlaymessage.below{padding-bottom:0;padding-top:8px;z-index:10000}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.monaco-editor .monaco-editor-overlaymessage.fadeIn{animation:fadeIn .15s ease-out}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}.monaco-editor .monaco-editor-overlaymessage.fadeOut{animation:fadeOut .1s ease-out}.monaco-editor .monaco-editor-overlaymessage .message{background-color:var(--vscode-inputValidation-infoBackground);border:1px solid var(--vscode-inputValidation-infoBorder);color:var(--vscode-inputValidation-infoForeground);padding:1px 4px}.monaco-editor.hc-black .monaco-editor-overlaymessage .message,.monaco-editor.hc-light .monaco-editor-overlaymessage .message{border-width:2px}.monaco-editor .monaco-editor-overlaymessage .anchor{border:8px solid transparent;height:0!important;position:absolute;width:0!important;z-index:1000}.monaco-editor .monaco-editor-overlaymessage .anchor.top{border-bottom-color:var(--vscode-inputValidation-infoBorder)}.monaco-editor .monaco-editor-overlaymessage .anchor.below{border-top-color:var(--vscode-inputValidation-infoBorder)}.monaco-editor .monaco-editor-overlaymessage.below .anchor.below,.monaco-editor .monaco-editor-overlaymessage:not(.below) .anchor.top{display:none}.monaco-editor .monaco-editor-overlaymessage.below .anchor.top{display:inherit;top:-8px}",""]),t.A=o},163:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .parameter-hints-widget{cursor:default;display:flex;flex-direction:column;line-height:1.5em;z-index:39}.monaco-editor .parameter-hints-widget>.phwrapper{display:flex;flex-direction:row;max-width:440px}.monaco-editor .parameter-hints-widget.multiple{min-height:3.3em;padding:0}.monaco-editor .parameter-hints-widget.visible{transition:left .05s ease-in-out}.monaco-editor .parameter-hints-widget p,.monaco-editor .parameter-hints-widget ul{margin:8px 0}.monaco-editor .parameter-hints-widget .body,.monaco-editor .parameter-hints-widget .monaco-scrollable-element{display:flex;flex:1;flex-direction:column;min-height:100%}.monaco-editor .parameter-hints-widget .signature{padding:4px 5px}.monaco-editor .parameter-hints-widget .docs{padding:0 10px 0 5px;white-space:pre-wrap}.monaco-editor .parameter-hints-widget .docs.empty{display:none}.monaco-editor .parameter-hints-widget .docs .markdown-docs{white-space:normal}.monaco-editor .parameter-hints-widget .docs .markdown-docs a:hover{cursor:pointer}.monaco-editor .parameter-hints-widget .docs .markdown-docs code{font-family:var(--monaco-monospace-font)}.monaco-editor .parameter-hints-widget .docs .code,.monaco-editor .parameter-hints-widget .docs .monaco-tokenized-source{white-space:pre-wrap}.monaco-editor .parameter-hints-widget .docs code{border-radius:3px;padding:0 .4em}.monaco-editor .parameter-hints-widget .controls{align-items:center;display:none;flex-direction:column;justify-content:flex-end;min-width:22px}.monaco-editor .parameter-hints-widget.multiple .controls{display:flex;padding:0 2px}.monaco-editor .parameter-hints-widget.multiple .button{background-repeat:no-repeat;cursor:pointer;height:16px;width:16px}.monaco-editor .parameter-hints-widget .button.previous{bottom:24px}.monaco-editor .parameter-hints-widget .overloads{font-family:var(--monaco-monospace-font);height:12px;line-height:12px;text-align:center}.monaco-editor .parameter-hints-widget .signature .parameter.active{font-weight:700}.monaco-editor .parameter-hints-widget .documentation-parameter>.parameter{font-weight:700;margin-right:.5em}",""]),t.A=o},226:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,'.monaco-editor .peekview-widget .head{box-sizing:border-box;display:flex;flex-wrap:nowrap;justify-content:space-between}.monaco-editor .peekview-widget .head .peekview-title{align-items:center;display:flex;font-size:13px;margin-left:20px;min-width:0;overflow:hidden;text-overflow:ellipsis}.monaco-editor .peekview-widget .head .peekview-title.clickable{cursor:pointer}.monaco-editor .peekview-widget .head .peekview-title .dirname:not(:empty){font-size:.9em;margin-left:.5em;overflow:hidden;text-overflow:ellipsis}.monaco-editor .peekview-widget .head .peekview-title .meta{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.monaco-editor .peekview-widget .head .peekview-title .dirname{white-space:nowrap}.monaco-editor .peekview-widget .head .peekview-title .filename{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.monaco-editor .peekview-widget .head .peekview-title .meta:not(:empty):before{content:"-";padding:0 .3em}.monaco-editor .peekview-widget .head .peekview-actions{flex:1;padding-right:2px;text-align:right}.monaco-editor .peekview-widget .head .peekview-actions>.monaco-action-bar{display:inline-block}.monaco-editor .peekview-widget .head .peekview-actions>.monaco-action-bar,.monaco-editor .peekview-widget .head .peekview-actions>.monaco-action-bar>.actions-container{height:100%}.monaco-editor .peekview-widget>.body{border-top:1px solid;position:relative}.monaco-editor .peekview-widget .head .peekview-title .codicon{margin-right:4px}.monaco-editor .peekview-widget .monaco-list .monaco-list-row.focused .codicon{color:inherit!important}',""]),t.A=o},4958:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .rename-box{color:inherit;z-index:100}.monaco-editor .rename-box.preview{padding:3px 3px 0}.monaco-editor .rename-box .rename-input{padding:3px;width:calc(100% - 6px)}.monaco-editor .rename-box .rename-label{display:none;opacity:.8}.monaco-editor .rename-box.preview .rename-label{display:inherit}",""]),t.A=o},8585:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .snippet-placeholder{background-color:var(--vscode-editor-snippetTabstopHighlightBackground,transparent);min-width:2px;outline-color:var(--vscode-editor-snippetTabstopHighlightBorder,transparent);outline-style:solid;outline-width:1px}.monaco-editor .finish-snippet-placeholder{background-color:var(--vscode-editor-snippetFinalTabstopHighlightBackground,transparent);outline-color:var(--vscode-editor-snippetFinalTabstopHighlightBorder,transparent);outline-style:solid;outline-width:1px}",""]),t.A=o},7484:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,'.monaco-editor .suggest-widget{display:flex;flex-direction:column;width:430px;z-index:40}.monaco-editor .suggest-widget.message{align-items:center;flex-direction:row}.monaco-editor .suggest-details,.monaco-editor .suggest-widget{background-color:var(--vscode-editorSuggestWidget-background);border-color:var(--vscode-editorSuggestWidget-border);border-style:solid;border-width:1px;flex:0 1 auto;width:100%}.monaco-editor.hc-black .suggest-details,.monaco-editor.hc-black .suggest-widget,.monaco-editor.hc-light .suggest-details,.monaco-editor.hc-light .suggest-widget{border-width:2px}.monaco-editor .suggest-widget .suggest-status-bar{border-top:1px solid var(--vscode-editorSuggestWidget-border);box-sizing:border-box;display:none;flex-flow:row nowrap;font-size:80%;justify-content:space-between;overflow:hidden;padding:0 4px;width:100%}.monaco-editor .suggest-widget.with-status-bar .suggest-status-bar{display:flex}.monaco-editor .suggest-widget .suggest-status-bar .left{padding-right:8px}.monaco-editor .suggest-widget.with-status-bar .suggest-status-bar .action-label{color:var(--vscode-editorSuggestWidgetStatus-foreground)}.monaco-editor .suggest-widget.with-status-bar .suggest-status-bar .action-item:not(:last-of-type) .action-label{margin-right:0}.monaco-editor .suggest-widget.with-status-bar .suggest-status-bar .action-item:not(:last-of-type) .action-label:after{content:", ";margin-right:.3em}.monaco-editor .suggest-widget.with-status-bar .monaco-list .monaco-list-row.focused.string-label>.contents>.main>.right>.readMore,.monaco-editor .suggest-widget.with-status-bar .monaco-list .monaco-list-row>.contents>.main>.right>.readMore{display:none}.monaco-editor .suggest-widget.with-status-bar:not(.docs-side) .monaco-list .monaco-list-row:hover>.contents>.main>.right.can-expand-details>.details-label{width:100%}.monaco-editor .suggest-widget>.message{padding-left:22px}.monaco-editor .suggest-widget>.tree{height:100%;width:100%}.monaco-editor .suggest-widget .monaco-list{-moz-user-select:none;user-select:none;-webkit-user-select:none;-ms-user-select:none}.monaco-editor .suggest-widget .monaco-list .monaco-list-row{background-position:2px 2px;background-repeat:no-repeat;-mox-box-sizing:border-box;box-sizing:border-box;cursor:pointer;display:flex;padding-right:10px;touch-action:none;white-space:nowrap}.monaco-editor .suggest-widget .monaco-list .monaco-list-row.focused{color:var(--vscode-editorSuggestWidget-selectedForeground)}.monaco-editor .suggest-widget .monaco-list .monaco-list-row.focused .codicon{color:var(--vscode-editorSuggestWidget-selectedIconForeground)}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents{flex:1;height:100%;overflow:hidden;padding-left:2px}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main{display:flex;justify-content:space-between;overflow:hidden;text-overflow:ellipsis;white-space:pre}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.left,.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.right{display:flex}.monaco-editor .suggest-widget .monaco-list .monaco-list-row:not(.focused)>.contents>.main .monaco-icon-label{color:var(--vscode-editorSuggestWidget-foreground)}.monaco-editor .suggest-widget:not(.frozen) .monaco-highlighted-label .highlight{font-weight:700}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main .monaco-highlighted-label .highlight{color:var(--vscode-editorSuggestWidget-highlightForeground)}.monaco-editor .suggest-widget .monaco-list .monaco-list-row.focused>.contents>.main .monaco-highlighted-label .highlight{color:var(--vscode-editorSuggestWidget-focusHighlightForeground)}.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.header>.codicon-close,.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.right>.readMore:before{color:inherit;cursor:pointer;font-size:14px;opacity:1}.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.header>.codicon-close{position:absolute;right:2px;top:6px}.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.header>.codicon-close:hover,.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.right>.readMore:hover{opacity:1}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.right>.details-label{opacity:.7}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.left>.signature-label{opacity:.6;overflow:hidden;text-overflow:ellipsis}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.left>.qualifier-label{align-self:center;font-size:85%;line-height:normal;margin-left:12px;opacity:.4;overflow:hidden;text-overflow:ellipsis}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.right>.details-label{font-size:85%;margin-left:1.1em;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.right>.details-label>.monaco-tokenized-source{display:inline}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.right>.details-label{display:none}.monaco-editor .suggest-widget .monaco-list .monaco-list-row:not(.string-label)>.contents>.main>.right>.details-label,.monaco-editor .suggest-widget.docs-side .monaco-list .monaco-list-row.focused:not(.string-label)>.contents>.main>.right>.details-label,.monaco-editor .suggest-widget:not(.shows-details) .monaco-list .monaco-list-row.focused>.contents>.main>.right>.details-label{display:inline}.monaco-editor .suggest-widget:not(.docs-side) .monaco-list .monaco-list-row.focused:hover>.contents>.main>.right.can-expand-details>.details-label{width:calc(100% - 26px)}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.left{flex-grow:1;flex-shrink:1;overflow:hidden}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.left>.monaco-icon-label{flex-shrink:0}.monaco-editor .suggest-widget .monaco-list .monaco-list-row:not(.string-label)>.contents>.main>.left>.monaco-icon-label{max-width:100%}.monaco-editor .suggest-widget .monaco-list .monaco-list-row.string-label>.contents>.main>.left>.monaco-icon-label{flex-shrink:1}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.right{flex-shrink:4;max-width:70%;overflow:hidden}.monaco-editor .suggest-widget .monaco-list .monaco-list-row>.contents>.main>.right>.readMore{display:inline-block;height:18px;position:absolute;right:10px;visibility:hidden;width:18px}.monaco-editor .suggest-widget.docs-side .monaco-list .monaco-list-row>.contents>.main>.right>.readMore{display:none!important}.monaco-editor .suggest-widget .monaco-list .monaco-list-row.string-label>.contents>.main>.right>.readMore{display:none}.monaco-editor .suggest-widget .monaco-list .monaco-list-row.focused.string-label>.contents>.main>.right>.readMore{display:inline-block}.monaco-editor .suggest-widget .monaco-list .monaco-list-row.focused:hover>.contents>.main>.right>.readMore{visibility:visible}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .monaco-icon-label.deprecated{opacity:.66;text-decoration:unset}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .monaco-icon-label.deprecated>.monaco-icon-label-container>.monaco-icon-name-container{text-decoration:line-through}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .monaco-icon-label:before{height:100%}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon{background-position:50%;background-repeat:no-repeat;background-size:80%;display:block;height:16px;margin-left:2px;width:16px}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.hide{display:none}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .suggest-icon{align-items:center;display:flex;margin-right:4px}.monaco-editor .suggest-widget.no-icons .monaco-list .monaco-list-row .icon,.monaco-editor .suggest-widget.no-icons .monaco-list .monaco-list-row .suggest-icon:before{display:none}.monaco-editor .suggest-widget .monaco-list .monaco-list-row .icon.customcolor .colorspan{border:.1em solid #000;display:inline-block;height:.7em;margin:0 0 0 .3em;width:.7em}.monaco-editor .suggest-details-container{z-index:41}.monaco-editor .suggest-details{color:var(--vscode-editorSuggestWidget-foreground);cursor:default;display:flex;flex-direction:column}.monaco-editor .suggest-details.focused{border-color:var(--vscode-focusBorder)}.monaco-editor .suggest-details a{color:var(--vscode-textLink-foreground)}.monaco-editor .suggest-details a:hover{color:var(--vscode-textLink-activeForeground)}.monaco-editor .suggest-details code{background-color:var(--vscode-textCodeBlock-background)}.monaco-editor .suggest-details.no-docs{display:none}.monaco-editor .suggest-details>.monaco-scrollable-element{flex:1}.monaco-editor .suggest-details>.monaco-scrollable-element>.body{box-sizing:border-box;height:100%;width:100%}.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.header>.type{flex:2;margin:0 24px 0 0;opacity:.7;overflow:hidden;padding:4px 0 12px 5px;text-overflow:ellipsis;white-space:pre}.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.header>.type.auto-wrap{white-space:normal;word-break:break-all}.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.docs{margin:0;padding:4px 5px;white-space:pre-wrap}.monaco-editor .suggest-details.no-type>.monaco-scrollable-element>.body>.docs{margin-right:24px;overflow:hidden}.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.docs.markdown-docs{min-height:calc(1rem + 8px);padding:0;white-space:normal}.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.docs.markdown-docs>div,.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.docs.markdown-docs>span:not(:empty){padding:4px 5px}.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.docs.markdown-docs>div>p:first-child{margin-top:0}.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.docs.markdown-docs>div>p:last-child{margin-bottom:0}.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.docs.markdown-docs .monaco-tokenized-source{white-space:pre}.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.docs .code{word-wrap:break-word;white-space:pre-wrap}.monaco-editor .suggest-details>.monaco-scrollable-element>.body>.docs.markdown-docs .codicon{vertical-align:sub}.monaco-editor .suggest-details>.monaco-scrollable-element>.body>p:empty{display:none}.monaco-editor .suggest-details code{border-radius:3px;padding:0 .4em}.monaco-editor .suggest-details ol,.monaco-editor .suggest-details ul{padding-left:20px}.monaco-editor .suggest-details p code{font-family:var(--monaco-monospace-font)}',""]),t.A=o},3389:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-editor .zone-widget{position:absolute;z-index:10}.monaco-editor .zone-widget .zone-widget-container{border-bottom-style:solid;border-bottom-width:0;border-top-style:solid;border-top-width:0;position:relative}",""]),t.A=o},170:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".quick-input-widget{font-size:13px}.quick-input-widget .monaco-highlighted-label .highlight{color:#0066bf}.vs .quick-input-widget .monaco-list-row.focused .monaco-highlighted-label .highlight{color:#9dddff}.vs-dark .quick-input-widget .monaco-highlighted-label .highlight{color:#0097fb}.hc-black .quick-input-widget .monaco-highlighted-label .highlight{color:#f38518}.hc-light .quick-input-widget .monaco-highlighted-label .highlight{color:#0f4a85}.monaco-keybinding>.monaco-keybinding-key{background-color:hsla(0,0%,87%,.4);border:1px solid hsla(0,0%,80%,.4);border-bottom-color:hsla(0,0%,73%,.4);box-shadow:inset 0 -1px 0 hsla(0,0%,73%,.4);color:#555}.hc-black .monaco-keybinding>.monaco-keybinding-key{background-color:transparent;border:1px solid #6fc3df;box-shadow:none;color:#fff}.hc-light .monaco-keybinding>.monaco-keybinding-key{background-color:transparent;border:1px solid #0f4a85;box-shadow:none;color:#292929}.vs-dark .monaco-keybinding>.monaco-keybinding-key{background-color:hsla(0,0%,50%,.17);border:1px solid rgba(51,51,51,.6);border-bottom-color:rgba(68,68,68,.6);box-shadow:inset 0 -1px 0 rgba(68,68,68,.6);color:#ccc}",""]),t.A=o},6514:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,'.monaco-editor{--monaco-monospace-font:"SF Mono",Monaco,Menlo,Consolas,"Ubuntu Mono","Liberation Mono","DejaVu Sans Mono","Courier New",monospace;font-family:-apple-system,BlinkMacSystemFont,Segoe WPC,Segoe UI,HelveticaNeue-Light,system-ui,Ubuntu,Droid Sans,sans-serif}.monaco-editor.hc-black .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label,.monaco-editor.hc-light .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label,.monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label,.monaco-menu .monaco-action-bar.vertical .action-item .action-menu-item:focus .action-label{stroke-width:1.2px}.monaco-hover p{margin:0}.monaco-aria-container{clip:rect(1px,1px,1px,1px);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute!important;top:0;width:1px}.monaco-editor.hc-black,.monaco-editor.hc-light{-ms-high-contrast-adjust:none}@media screen and (-ms-high-contrast:active){.monaco-editor.vs .view-overlays .current-line,.monaco-editor.vs-dark .view-overlays .current-line{border-color:windowtext!important;border-left:0;border-right:0}.monaco-editor.vs .cursor,.monaco-editor.vs-dark .cursor{background-color:windowtext!important}.monaco-editor.vs .dnd-target,.monaco-editor.vs-dark .dnd-target{border-color:windowtext!important}.monaco-editor.vs .selected-text,.monaco-editor.vs-dark .selected-text{background-color:highlight!important}.monaco-editor.vs .view-line,.monaco-editor.vs-dark .view-line{-ms-high-contrast-adjust:none}.monaco-editor.vs .view-line span,.monaco-editor.vs-dark .view-line span{color:windowtext!important}.monaco-editor.vs .view-line span.inline-selected-text,.monaco-editor.vs-dark .view-line span.inline-selected-text{color:highlighttext!important}.monaco-editor.vs .view-overlays,.monaco-editor.vs-dark .view-overlays{-ms-high-contrast-adjust:none}.monaco-editor.vs .reference-decoration,.monaco-editor.vs .selectionHighlight,.monaco-editor.vs .wordHighlight,.monaco-editor.vs .wordHighlightStrong,.monaco-editor.vs-dark .reference-decoration,.monaco-editor.vs-dark .selectionHighlight,.monaco-editor.vs-dark .wordHighlight,.monaco-editor.vs-dark .wordHighlightStrong{background:transparent!important;border:2px dotted highlight!important;box-sizing:border-box}.monaco-editor.vs .rangeHighlight,.monaco-editor.vs-dark .rangeHighlight{background:transparent!important;border:1px dotted activeborder!important;box-sizing:border-box}.monaco-editor.vs .bracket-match,.monaco-editor.vs-dark .bracket-match{background:transparent!important;border-color:windowtext!important}.monaco-editor.vs .currentFindMatch,.monaco-editor.vs .findMatch,.monaco-editor.vs-dark .currentFindMatch,.monaco-editor.vs-dark .findMatch{background:transparent!important;border:2px dotted activeborder!important;box-sizing:border-box}.monaco-editor.vs .find-widget,.monaco-editor.vs-dark .find-widget{border:1px solid windowtext}.monaco-editor.vs .monaco-list .monaco-list-row,.monaco-editor.vs-dark .monaco-list .monaco-list-row{-ms-high-contrast-adjust:none;color:windowtext!important}.monaco-editor.vs .monaco-list .monaco-list-row.focused,.monaco-editor.vs-dark .monaco-list .monaco-list-row.focused{background-color:highlight!important;color:highlighttext!important}.monaco-editor.vs .monaco-list .monaco-list-row:hover,.monaco-editor.vs-dark .monaco-list .monaco-list-row:hover{background:transparent!important;border:1px solid highlight;box-sizing:border-box}.monaco-editor.vs .monaco-scrollable-element>.scrollbar,.monaco-editor.vs-dark .monaco-scrollable-element>.scrollbar{-ms-high-contrast-adjust:none;background:background!important;border:1px solid windowtext;box-sizing:border-box}.monaco-editor.vs .monaco-scrollable-element>.scrollbar>.slider,.monaco-editor.vs-dark .monaco-scrollable-element>.scrollbar>.slider{background:windowtext!important}.monaco-editor.vs .monaco-scrollable-element>.scrollbar>.slider.active,.monaco-editor.vs .monaco-scrollable-element>.scrollbar>.slider:hover,.monaco-editor.vs-dark .monaco-scrollable-element>.scrollbar>.slider.active,.monaco-editor.vs-dark .monaco-scrollable-element>.scrollbar>.slider:hover{background:highlight!important}.monaco-editor.vs .decorationsOverviewRuler,.monaco-editor.vs-dark .decorationsOverviewRuler{opacity:0}.monaco-editor.vs .minimap,.monaco-editor.vs-dark .minimap{display:none}.monaco-editor.vs .squiggly-d-error,.monaco-editor.vs-dark .squiggly-d-error{background:transparent!important;border-bottom:4px double #e47777}.monaco-editor.vs .squiggly-b-info,.monaco-editor.vs .squiggly-c-warning,.monaco-editor.vs-dark .squiggly-b-info,.monaco-editor.vs-dark .squiggly-c-warning{border-bottom:4px double #71b771}.monaco-editor.vs .squiggly-a-hint,.monaco-editor.vs-dark .squiggly-a-hint{border-bottom:4px double #6c6c6c}.monaco-editor.vs .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label,.monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-menu-item:focus .action-label{-ms-high-contrast-adjust:none;background-color:highlight!important;color:highlighttext!important}.monaco-editor.vs .monaco-menu .monaco-action-bar.vertical .action-menu-item:hover .action-label,.monaco-editor.vs-dark .monaco-menu .monaco-action-bar.vertical .action-menu-item:hover .action-label{-ms-high-contrast-adjust:none;background:transparent!important;border:1px solid highlight;box-sizing:border-box}.monaco-diff-editor.vs .diffOverviewRuler,.monaco-diff-editor.vs-dark .diffOverviewRuler{display:none}.monaco-editor.vs .line-delete,.monaco-editor.vs .line-insert,.monaco-editor.vs-dark .line-delete,.monaco-editor.vs-dark .line-insert{background:transparent!important;border:1px solid highlight!important;box-sizing:border-box}.monaco-editor.vs .char-delete,.monaco-editor.vs .char-insert,.monaco-editor.vs-dark .char-delete,.monaco-editor.vs-dark .char-insert{background:transparent!important}}',""]),t.A=o},7619:function(e,t,i){"use strict";var n=i(186),o=i.n(n)()(function(e){return e[1]});o.push([e.id,".monaco-action-bar .action-item.menu-entry .action-label.icon{background-position:50%;background-repeat:no-repeat;background-size:16px;height:16px;width:16px}.monaco-dropdown-with-default{border-radius:5px;display:flex!important;flex-direction:row}.monaco-dropdown-with-default>.action-container>.action-label{margin-right:0}.monaco-dropdown-with-default>.action-container.menu-entry>.action-label.icon{background-position:50%;background-repeat:no-repeat;background-size:16px;height:16px;width:16px}.monaco-dropdown-with-default>.dropdown-action-container>.monaco-dropdown>.dropdown-label .codicon[class*=codicon-]{font-size:12px;line-height:16px;margin-left:-3px;padding-left:0;padding-right:0}.monaco-dropdown-with-default>.dropdown-action-container>.monaco-dropdown>.dropdown-label>.action-label{background-position:50%;background-repeat:no-repeat;background-size:16px;display:block}",""]),t.A=o},186:function(e){"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map(function(t){var i=e(t);return t[2]?"@media ".concat(t[2]," {").concat(i,"}"):i}).join("")},t.i=function(e,i,n){"string"==typeof e&&(e=[[null,e,""]]);var o={};if(n)for(var s=0;s0;){10===e.charCodeAt(o)?(o++,s++,r=0):(o++,r++),t--}}function l(e){null===i?o=e:a(e-o)}function h(){for(;o0&&65279===e.charCodeAt(0)&&(o=1);var g=0,p=null,m=[],f=[],_=null;function v(e,t){m.push(g),f.push(p),g=e,p=t}function b(){if(0===m.length)return w("illegal state stack");g=m.pop(),p=f.pop()}function w(t){throw new Error("Near offset "+o+": "+t+" ~~~"+e.substr(o,50)+"~~~")}var C=function(){if(null===_)return w("missing ");var e={};null!==i&&(e[i]={filename:t,line:s,char:r}),p[_]=e,_=null,v(1,e)},y=function(){if(null===_)return w("missing ");var e=[];p[_]=e,_=null,v(2,e)},S=function(){var e={};null!==i&&(e[i]={filename:t,line:s,char:r}),p.push(e),v(1,e)},k=function(){var e=[];p.push(e),v(2,e)};function L(){1===g?C():2===g?S():(p={},null!==i&&(p[i]={filename:t,line:s,char:r}),v(1,p))}function x(){if(1!==g)return w("unexpected ");b()}function D(){1===g?y():2===g?k():v(2,p=[])}function E(){return 1===g||2!==g?w("unexpected "):void b()}function N(e){return 1!==g?w("unexpected "):null!==_?w("too many "):void(_=e)}function I(e){if(1===g){if(null===_)return w("missing ");p[_]=e,_=null}else 2===g?p.push(e):p=e}function M(e){if(isNaN(e))return w("cannot parse float");if(1===g){if(null===_)return w("missing ");p[_]=e,_=null}else 2===g?p.push(e):p=e}function T(e){if(isNaN(e))return w("cannot parse integer");if(1===g){if(null===_)return w("missing ");p[_]=e,_=null}else 2===g?p.push(e):p=e}function A(e){if(1===g){if(null===_)return w("missing ");p[_]=e,_=null}else 2===g?p.push(e):p=e}function O(e){if(1===g){if(null===_)return w("missing ");p[_]=e,_=null}else 2===g?p.push(e):p=e}function R(e){if(1===g){if(null===_)return w("missing ");p[_]=e,_=null}else 2===g?p.push(e):p=e}function P(){var e=u(">"),t=!1;return 47===e.charCodeAt(e.length-1)&&(t=!0,e=e.substring(0,e.length-1)),{name:e.trim(),isClosed:t}}function F(e){if(e.isClosed)return"";var t=u(""),t.replace(/&#([0-9]+);/g,function(e,t){return String.fromCodePoint(parseInt(t,10))}).replace(/&#x([0-9a-f]+);/g,function(e,t){return String.fromCodePoint(parseInt(t,16))}).replace(/&|<|>|"|'/g,function(e){switch(e){case"&":return"&";case"<":return"<";case">":return">";case""":return'"';case"'":return"'"}return e})}for(;o=n));){var B=e.charCodeAt(o);if(a(1),60!==B)return w("expected <");if(o>=n)return w("unexpected end of input");var V=e.charCodeAt(o);if(63!==V)if(33!==V){if(47===V){if(a(1),h(),d("plist")){c(">");continue}if(d("dict")){c(">"),x();continue}if(d("array")){c(">"),E();continue}return w("unexpected closed tag")}var W=P();switch(W.name){case"dict":L(),W.isClosed&&x();continue;case"array":D(),W.isClosed&&E();continue;case"key":N(F(W));continue;case"string":I(F(W));continue;case"real":M(parseFloat(F(W)));continue;case"integer":T(parseInt(F(W),10));continue;case"date":A(new Date(F(W)));continue;case"data":O(F(W));continue;case"true":F(W),R(!0);continue;case"false":F(W),R(!1);continue}if(!/^plist/.test(W.name))return w("unexpected opened tag "+W.name)}else{if(a(1),d("--")){c("--\x3e");continue}c(">")}else a(1),c("?>")}return p}t.qg=void 0,t.qg=function(e){return i(e,null,null)}},4331:function(e,t){ +/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh */ +t.read=function(e,t,i,n,o){var s,r,a=8*o-n-1,l=(1<>1,d=-7,c=i?o-1:0,u=i?-1:1,g=e[t+c];for(c+=u,s=g&(1<<-d)-1,g>>=-d,d+=a;d>0;s=256*s+e[t+c],c+=u,d-=8);for(r=s&(1<<-d)-1,s>>=-d,d+=n;d>0;r=256*r+e[t+c],c+=u,d-=8);if(0===s)s=1-h;else{if(s===l)return r?NaN:1/0*(g?-1:1);r+=Math.pow(2,n),s-=h}return(g?-1:1)*r*Math.pow(2,s-n)},t.write=function(e,t,i,n,o,s){var r,a,l,h=8*s-o-1,d=(1<>1,u=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,g=n?0:s-1,p=n?1:-1,m=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,r=d):(r=Math.floor(Math.log(t)/Math.LN2),t*(l=Math.pow(2,-r))<1&&(r--,l*=2),(t+=r+c>=1?u/l:u*Math.pow(2,1-c))*l>=2&&(r++,l/=2),r+c>=d?(a=0,r=d):r+c>=1?(a=(t*l-1)*Math.pow(2,o),r+=c):(a=t*Math.pow(2,c-1)*Math.pow(2,o),r=0));o>=8;e[i+g]=255&a,g+=p,a/=256,o-=8);for(r=r<0;e[i+g]=255&r,g+=p,r/=256,h-=8);e[i+g-p]|=128*m}},8346:function(e){var t={}.toString;e.exports=Array.isArray||function(e){return"[object Array]"==t.call(e)}},2584:function(){},9201:function(e,t,i){"use strict";i.r(t),i.d(t,{CancellationTokenSource:function(){return Z5},Emitter:function(){return Y5},KeyCode:function(){return Q5},KeyMod:function(){return X5},MarkerSeverity:function(){return n3},MarkerTag:function(){return o3},Position:function(){return J5},Range:function(){return e3},Selection:function(){return t3},SelectionDirection:function(){return i3},Token:function(){return r3},Uri:function(){return s3},default:function(){return H3},editor:function(){return a3},languages:function(){return l3}});var n={};i.r(n),i.d(n,{PixelRatio:function(){return je},addMatchMediaChangeListener:function(){return Ue},getZoomFactor:function(){return Ke},isAndroid:function(){return Je},isChrome:function(){return Ze},isElectron:function(){return Xe},isFirefox:function(){return qe},isSafari:function(){return Ye},isStandalone:function(){return tt},isWebKit:function(){return Ge},isWebkitWebView:function(){return Qe}});var o={};i.r(o),i.d(o,{CancellationTokenSource:function(){return Z5},Emitter:function(){return Y5},KeyCode:function(){return Q5},KeyMod:function(){return X5},MarkerSeverity:function(){return n3},MarkerTag:function(){return o3},Position:function(){return J5},Range:function(){return e3},Selection:function(){return t3},SelectionDirection:function(){return i3},Token:function(){return r3},Uri:function(){return s3},editor:function(){return a3},languages:function(){return l3}});var s={};i.r(s),i.d(s,{CancellationTokenSource:function(){return Z5},Emitter:function(){return Y5},KeyCode:function(){return Q5},KeyMod:function(){return X5},MarkerSeverity:function(){return n3},MarkerTag:function(){return o3},Position:function(){return J5},Range:function(){return e3},Selection:function(){return t3},SelectionDirection:function(){return i3},Token:function(){return r3},Uri:function(){return s3},default:function(){return H3},editor:function(){return a3},languages:function(){return l3}});const r=new class{constructor(){this.listeners=[],this.unexpectedErrorHandler=function(e){setTimeout(()=>{if(e.stack){if(f.isErrorNoTelemetry(e))throw new f(e.message+"\n\n"+e.stack);throw new Error(e.message+"\n\n"+e.stack)}throw e},0)}}emit(e){this.listeners.forEach(t=>{t(e)})}onUnexpectedError(e){this.unexpectedErrorHandler(e),this.emit(e)}onUnexpectedExternalError(e){this.unexpectedErrorHandler(e)}};function a(e){c(e)||r.onUnexpectedError(e)}function l(e){c(e)||r.onUnexpectedExternalError(e)}function h(e){if(e instanceof Error){const{name:t,message:i}=e;return{$isError:!0,name:t,message:i,stack:e.stacktrace||e.stack,noTelemetry:f.isErrorNoTelemetry(e)}}return e}const d="Canceled";function c(e){return e instanceof u||e instanceof Error&&e.name===d&&e.message===d}class u extends Error{constructor(){super(d),this.name=this.message}}function g(){const e=new Error(d);return e.name=e.message,e}function p(e){return e?new Error(`Illegal argument: ${e}`):new Error("Illegal argument")}class m extends Error{constructor(e){super("NotSupported"),e&&(this.message=e)}}class f extends Error{constructor(e){super(e),this.name="ErrorNoTelemetry"}static fromError(e){if(e instanceof f)return e;const t=new f;return t.message=e.message,t.stack=e.stack,t}static isErrorNoTelemetry(e){return"ErrorNoTelemetry"===e.name}}class _ extends Error{constructor(e){super(e||"An unexpected bug occurred."),Object.setPrototypeOf(this,_.prototype)}}function v(e){const t=this;let i,n=!1;return function(){return n||(n=!0,i=e.apply(t,arguments)),i}}var b;!function(e){e.is=function(e){return e&&"object"==typeof e&&"function"==typeof e[Symbol.iterator]};const t=Object.freeze([]);function i(t,i=Number.POSITIVE_INFINITY){const n=[];if(0===i)return[n,t];const o=t[Symbol.iterator]();for(let t=0;te.length&&(i=e.length);te===t){const n=e[Symbol.iterator](),o=t[Symbol.iterator]();for(;;){const e=n.next(),t=o.next();if(e.done!==t.done)return!1;if(e.done)return!0;if(!i(e.value,t.value))return!1}}}(b||(b={}));let w=null;function C(e){return null==w||w.trackDisposable(e),e}function y(e){null==w||w.markAsDisposed(e)}function S(e,t){null==w||w.setParent(e,t)}function k(e){return null==w||w.markAsSingleton(e),e}class L extends Error{constructor(e){super(`Encountered errors while disposing of store. Errors: [${e.join(", ")}]`),this.errors=e}}function x(e){return"function"==typeof e.dispose&&0===e.dispose.length}function D(e){if(b.is(e)){const t=[];for(const i of e)if(i)try{i.dispose()}catch(e){t.push(e)}if(1===t.length)throw t[0];if(t.length>1)throw new L(t);return Array.isArray(e)?[]:e}if(e)return e.dispose(),e}function E(...e){const t=N(()=>D(e));return function(e,t){if(w)for(const i of e)w.setParent(i,t)}(e,t),t}function N(e){const t=C({dispose:v(()=>{y(t),e()})});return t}class I{constructor(){this._toDispose=new Set,this._isDisposed=!1,C(this)}dispose(){this._isDisposed||(y(this),this._isDisposed=!0,this.clear())}get isDisposed(){return this._isDisposed}clear(){try{D(this._toDispose.values())}finally{this._toDispose.clear()}}add(e){if(!e)return e;if(e===this)throw new Error("Cannot register a disposable on itself!");return S(e,this),this._isDisposed?I.DISABLE_DISPOSED_WARNING||console.warn(new Error("Trying to add a disposable to a DisposableStore that has already been disposed of. The added object will be leaked!").stack):this._toDispose.add(e),e}}I.DISABLE_DISPOSED_WARNING=!1;class M{constructor(){this._store=new I,C(this),S(this._store,this)}dispose(){y(this),this._store.dispose()}_register(e){if(e===this)throw new Error("Cannot register a disposable on itself!");return this._store.add(e)}}M.None=Object.freeze({dispose(){}});class T{constructor(){this._isDisposed=!1,C(this)}get value(){return this._isDisposed?void 0:this._value}set value(e){var t;this._isDisposed||e===this._value||(null===(t=this._value)||void 0===t||t.dispose(),e&&S(e,this),this._value=e)}clear(){this.value=void 0}dispose(){var e;this._isDisposed=!0,y(this),null===(e=this._value)||void 0===e||e.dispose(),this._value=void 0}clearAndLeak(){const e=this._value;return this._value=void 0,e&&S(e,null),e}}class A{constructor(e){this._disposable=e,this._counter=1}acquire(){return this._counter++,this}release(){return 0===--this._counter&&this._disposable.dispose(),this}}class O{constructor(){this.dispose=()=>{},this.unset=()=>{},this.isset=()=>!1,C(this)}set(e){let t=e;return this.unset=()=>t=void 0,this.isset=()=>void 0!==t,this.dispose=()=>{t&&(t(),t=void 0,y(this))},this}}class R{constructor(e){this.object=e}dispose(){}}class P{constructor(e){this.element=e,this.next=P.Undefined,this.prev=P.Undefined}}P.Undefined=new P(void 0);class F{constructor(){this._first=P.Undefined,this._last=P.Undefined,this._size=0}get size(){return this._size}isEmpty(){return this._first===P.Undefined}clear(){let e=this._first;for(;e!==P.Undefined;){const t=e.next;e.prev=P.Undefined,e.next=P.Undefined,e=t}this._first=P.Undefined,this._last=P.Undefined,this._size=0}unshift(e){return this._insert(e,!1)}push(e){return this._insert(e,!0)}_insert(e,t){const i=new P(e);if(this._first===P.Undefined)this._first=i,this._last=i;else if(t){const e=this._last;this._last=i,i.prev=e,e.next=i}else{const e=this._first;this._first=i,i.next=e,e.prev=i}this._size+=1;let n=!1;return()=>{n||(n=!0,this._remove(i))}}shift(){if(this._first!==P.Undefined){const e=this._first.element;return this._remove(this._first),e}}pop(){if(this._last!==P.Undefined){const e=this._last.element;return this._remove(this._last),e}}_remove(e){if(e.prev!==P.Undefined&&e.next!==P.Undefined){const t=e.prev;t.next=e.next,e.next.prev=t}else e.prev===P.Undefined&&e.next===P.Undefined?(this._first=P.Undefined,this._last=P.Undefined):e.next===P.Undefined?(this._last=this._last.prev,this._last.next=P.Undefined):e.prev===P.Undefined&&(this._first=this._first.next,this._first.prev=P.Undefined);this._size-=1}*[Symbol.iterator](){let e=this._first;for(;e!==P.Undefined;)yield e.element,e=e.next}}let B="undefined"!=typeof document&&document.location&&document.location.hash.indexOf("pseudo=true")>=0;function V(e,t){let i;return i=0===t.length?e:e.replace(/\{(\d+)\}/g,(e,i)=>{const n=i[0],o=t[n];let s=e;return"string"==typeof o?s=o:"number"!=typeof o&&"boolean"!=typeof o&&null!=o||(s=String(o)),s}),B&&(i="["+i.replace(/[aouei]/g,"$&$&")+"]"),i}function W(e,t,...i){return V(t,i)}var z,H=i(4806);const U="en";let j,K,$=!1,q=!1,G=!1,Z=!1,Y=!1,Q=!1,X=!1,J=!1,ee=!1,te=null,ie=null;const ne="object"==typeof self?self:"object"==typeof i.g?i.g:{};let oe;void 0!==ne.vscode&&void 0!==ne.vscode.process?oe=ne.vscode.process:void 0!==H&&(oe=H);const se="string"==typeof(null===(z=null==oe?void 0:oe.versions)||void 0===z?void 0:z.electron),re=se&&"renderer"===(null==oe?void 0:oe.type);if("object"!=typeof navigator||re)if("object"==typeof oe){$="win32"===oe.platform,q="darwin"===oe.platform,G="linux"===oe.platform,Z=G&&!!oe.env.SNAP&&!!oe.env.SNAP_REVISION,X=se,ee=!!oe.env.CI||!!oe.env.BUILD_ARTIFACTSTAGINGDIRECTORY,j=U,te=U;const e=oe.env.VSCODE_NLS_CONFIG;if(e)try{const t=JSON.parse(e),i=t.availableLanguages["*"];j=t.locale,te=i||U,ie=t._translationsConfigFile}catch(e){}Y=!0}else console.error("Unable to resolve platform.");else{K=navigator.userAgent,$=K.indexOf("Windows")>=0,q=K.indexOf("Macintosh")>=0,J=(K.indexOf("Macintosh")>=0||K.indexOf("iPad")>=0||K.indexOf("iPhone")>=0)&&!!navigator.maxTouchPoints&&navigator.maxTouchPoints>0,G=K.indexOf("Linux")>=0,Q=!0;j=void W(0,"_")||U,te=j}let ae=0;q?ae=1:$?ae=3:G&&(ae=2);const le=$,he=q,de=G,ce=Y,ue=Q,ge=Q&&"function"==typeof ne.importScripts,pe=J,me=K,fe="function"==typeof ne.postMessage&&!ne.importScripts,_e=(()=>{if(fe){const e=[];ne.addEventListener("message",t=>{if(t.data&&t.data.vscodeScheduleAsyncWork)for(let i=0,n=e.length;i{const n=++t;e.push({id:n,callback:i}),ne.postMessage({vscodeScheduleAsyncWork:n},"*")}}return e=>setTimeout(e)})(),ve=q||J?2:$?1:3;let be=!0,we=!1;function Ce(){if(!we){we=!0;const e=new Uint8Array(2);e[0]=1,e[1]=2;const t=new Uint16Array(e.buffer);be=513===t[0]}return be}const ye=!!(me&&me.indexOf("Chrome")>=0),Se=!!(me&&me.indexOf("Firefox")>=0),ke=!!(!ye&&me&&me.indexOf("Safari")>=0),Le=!!(me&&me.indexOf("Edg/")>=0),xe=(me&&me.indexOf("Android"),ne.performance&&"function"==typeof ne.performance.now);class De{constructor(e){this._highResolution=xe&&e,this._startTime=this._now(),this._stopTime=-1}static create(e=!0){return new De(e)}stop(){this._stopTime=this._now()}elapsed(){return-1!==this._stopTime?this._stopTime-this._startTime:this._now()-this._startTime}_now(){return this._highResolution?ne.performance.now():Date.now()}}var Ee;!function(e){function t(e){false}function i(e){return(t,i=null,n)=>{let o,s=!1;return o=e(e=>{if(!s)return o?o.dispose():s=!0,t.call(i,e)},null,n),s&&o.dispose(),o}}function n(e,t,i){return a((i,n=null,o)=>e(e=>i.call(n,t(e)),null,o),i)}function o(e,t,i){return a((i,n=null,o)=>e(e=>{t(e),i.call(n,e)},null,o),i)}function s(e,t,i){return a((i,n=null,o)=>e(e=>t(e)&&i.call(n,e),null,o),i)}function r(e,t,i,o){let s=i;return n(e,e=>(s=t(s,e),s),o)}function a(e,i){let n;const o={onFirstListenerAdd(){n=e(s.fire,s)},onLastListenerRemove(){null==n||n.dispose()}};i||t();const s=new Te(o);return null==i||i.add(s),s.event}function l(e,i,n=100,o=!1,s,r){let a,l,h,d=0;const c={leakWarningThreshold:s,onFirstListenerAdd(){a=e(e=>{d++,l=i(l,e),o&&!h&&(u.fire(l),l=void 0),clearTimeout(h),h=setTimeout(()=>{const e=l;l=void 0,h=void 0,(!o||d>1)&&u.fire(e),d=0},n)})},onLastListenerRemove(){a.dispose()}};r||t();const u=new Te(c);return null==r||r.add(u),u.event}function h(e,t=(e,t)=>e===t,i){let n,o=!0;return s(e,e=>{const i=o||!t(e,n);return o=!1,n=e,i},i)}e.None=()=>M.None,e.once=i,e.map=n,e.forEach=o,e.filter=s,e.signal=function(e){return e},e.any=function(...e){return(t,i=null,n)=>E(...e.map(e=>e(e=>t.call(i,e),null,n)))},e.reduce=r,e.debounce=l,e.latch=h,e.split=function(t,i,n){return[e.filter(t,i,n),e.filter(t,e=>!i(e),n)]},e.buffer=function(e,t=!1,i=[]){let n=i.slice(),o=e(e=>{n?n.push(e):r.fire(e)});const s=()=>{null==n||n.forEach(e=>r.fire(e)),n=null},r=new Te({onFirstListenerAdd(){o||(o=e(e=>r.fire(e)))},onFirstListenerDidAdd(){n&&(t?setTimeout(s):s())},onLastListenerRemove(){o&&o.dispose(),o=null}});return r.event};class d{constructor(e){this.event=e,this.disposables=new I}map(e){return new d(n(this.event,e,this.disposables))}forEach(e){return new d(o(this.event,e,this.disposables))}filter(e){return new d(s(this.event,e,this.disposables))}reduce(e,t){return new d(r(this.event,e,t,this.disposables))}latch(){return new d(h(this.event,void 0,this.disposables))}debounce(e,t=100,i=!1,n){return new d(l(this.event,e,t,i,n,this.disposables))}on(e,t,i){return this.event(e,t,i)}once(e,t,n){return i(this.event)(e,t,n)}dispose(){this.disposables.dispose()}}e.chain=function(e){return new d(e)},e.fromNodeEventEmitter=function(e,t,i=e=>e){const n=(...e)=>o.fire(i(...e)),o=new Te({onFirstListenerAdd:()=>e.on(t,n),onLastListenerRemove:()=>e.removeListener(t,n)});return o.event},e.fromDOMEventEmitter=function(e,t,i=e=>e){const n=(...e)=>o.fire(i(...e)),o=new Te({onFirstListenerAdd:()=>e.addEventListener(t,n),onLastListenerRemove:()=>e.removeEventListener(t,n)});return o.event},e.toPromise=function(e){return new Promise(t=>i(e)(t))},e.runAndSubscribe=function(e,t){return t(void 0),e(e=>t(e))},e.runAndSubscribeWithStore=function(e,t){let i=null;function n(e){null==i||i.dispose(),i=new I,t(e,i)}n(void 0);const o=e(e=>n(e));return N(()=>{o.dispose(),null==i||i.dispose()})};class c{constructor(e,i){this.obs=e,this._counter=0,this._hasChanged=!1;const n={onFirstListenerAdd:()=>{e.addObserver(this)},onLastListenerRemove:()=>{e.removeObserver(this)}};i||t(),this.emitter=new Te(n),i&&i.add(this.emitter)}beginUpdate(e){this._counter++}handleChange(e,t){this._hasChanged=!0}endUpdate(e){0===--this._counter&&this._hasChanged&&(this._hasChanged=!1,this.emitter.fire(this.obs.get()))}}e.fromObservable=function(e,t){return new c(e,t).emitter.event}}(Ee||(Ee={}));class Ne{constructor(e){this._listenerCount=0,this._invocationCount=0,this._elapsedOverall=0,this._name=`${e}_${Ne._idPool++}`}start(e){this._stopWatch=new De(!0),this._listenerCount=e}stop(){if(this._stopWatch){const e=this._stopWatch.elapsed();this._elapsedOverall+=e,this._invocationCount+=1,console.info(`did FIRE ${this._name}: elapsed_ms: ${e.toFixed(5)}, listener: ${this._listenerCount} (elapsed_overall: ${this._elapsedOverall.toFixed(2)}, invocations: ${this._invocationCount})`),this._stopWatch=void 0}}}Ne._idPool=0;class Ie{constructor(e){this.value=e}static create(){var e;return new Ie(null!==(e=(new Error).stack)&&void 0!==e?e:"")}print(){console.warn(this.value.split("\n").slice(2).join("\n"))}}class Me{constructor(e,t,i){this.callback=e,this.callbackThis=t,this.stack=i,this.subscription=new O}invoke(e){this.callback.call(this.callbackThis,e)}}class Te{constructor(e){var t,i;this._disposed=!1,this._options=e,this._leakageMon=void 0,this._perfMon=(null===(t=this._options)||void 0===t?void 0:t._profName)?new Ne(this._options._profName):void 0,this._deliveryQueue=null===(i=this._options)||void 0===i?void 0:i.deliveryQueue}dispose(){var e,t,i,n;this._disposed||(this._disposed=!0,this._listeners&&this._listeners.clear(),null===(e=this._deliveryQueue)||void 0===e||e.clear(this),null===(i=null===(t=this._options)||void 0===t?void 0:t.onLastListenerRemove)||void 0===i||i.call(t),null===(n=this._leakageMon)||void 0===n||n.dispose())}get event(){return this._event||(this._event=(e,t,i)=>{var n,o,s;this._listeners||(this._listeners=new F);const r=this._listeners.isEmpty();let a,l;r&&(null===(n=this._options)||void 0===n?void 0:n.onFirstListenerAdd)&&this._options.onFirstListenerAdd(this),this._leakageMon&&this._listeners.size>=30&&(l=Ie.create(),a=this._leakageMon.check(l,this._listeners.size+1));const h=new Me(e,t,l),d=this._listeners.push(h);r&&(null===(o=this._options)||void 0===o?void 0:o.onFirstListenerDidAdd)&&this._options.onFirstListenerDidAdd(this),(null===(s=this._options)||void 0===s?void 0:s.onListenerDidAdd)&&this._options.onListenerDidAdd(this,e,t);const c=h.subscription.set(()=>{if(null==a||a(),!this._disposed&&(d(),this._options&&this._options.onLastListenerRemove)){this._listeners&&!this._listeners.isEmpty()||this._options.onLastListenerRemove(this)}});return i instanceof I?i.add(c):Array.isArray(i)&&i.push(c),c}),this._event}fire(e){var t,i;if(this._listeners){this._deliveryQueue||(this._deliveryQueue=new Oe);for(const t of this._listeners)this._deliveryQueue.push(this,t,e);null===(t=this._perfMon)||void 0===t||t.start(this._deliveryQueue.size),this._deliveryQueue.deliver(),null===(i=this._perfMon)||void 0===i||i.stop()}}}class Ae{constructor(){this._queue=new F}get size(){return this._queue.size}push(e,t,i){this._queue.push(new Re(e,t,i))}clear(e){const t=new F;for(const i of this._queue)i.emitter!==e&&t.push(i);this._queue=t}deliver(){for(;this._queue.size>0;){const e=this._queue.shift();try{e.listener.invoke(e.event)}catch(e){a(e)}}}}class Oe extends Ae{clear(e){this._queue.clear()}}class Re{constructor(e,t,i){this.emitter=e,this.listener=t,this.event=i}}class Pe extends Te{constructor(e){super(e),this._isPaused=0,this._eventQueue=new F,this._mergeFn=null==e?void 0:e.merge}pause(){this._isPaused++}resume(){if(0!==this._isPaused&&0===--this._isPaused)if(this._mergeFn){const e=Array.from(this._eventQueue);this._eventQueue.clear(),super.fire(this._mergeFn(e))}else for(;!this._isPaused&&0!==this._eventQueue.size;)super.fire(this._eventQueue.shift())}fire(e){this._listeners&&(0!==this._isPaused?this._eventQueue.push(e):super.fire(e))}}class Fe extends Pe{constructor(e){var t;super(e),this._delay=null!==(t=e.delay)&&void 0!==t?t:100}fire(e){this._handle||(this.pause(),this._handle=setTimeout(()=>{this._handle=void 0,this.resume()},this._delay)),super.fire(e)}}class Be{constructor(){this.buffers=[]}wrapEvent(e){return(t,i,n)=>e(e=>{const n=this.buffers[this.buffers.length-1];n?n.push(()=>t.call(i,e)):t.call(i,e)},void 0,n)}bufferEvents(e){const t=[];this.buffers.push(t);const i=e();return this.buffers.pop(),t.forEach(e=>e()),i}}class Ve{constructor(){this.listening=!1,this.inputEvent=Ee.None,this.inputEventListener=M.None,this.emitter=new Te({onFirstListenerDidAdd:()=>{this.listening=!0,this.inputEventListener=this.inputEvent(this.emitter.fire,this.emitter)},onLastListenerRemove:()=>{this.listening=!1,this.inputEventListener.dispose()}}),this.event=this.emitter.event}set input(e){this.inputEvent=e,this.listening&&(this.inputEventListener.dispose(),this.inputEventListener=e(this.emitter.fire,this.emitter))}dispose(){this.inputEventListener.dispose(),this.emitter.dispose()}}class We{constructor(){this._zoomFactor=1}getZoomFactor(){return this._zoomFactor}}We.INSTANCE=new We;class ze extends M{constructor(){super(),this._onDidChange=this._register(new Te),this.onDidChange=this._onDidChange.event,this._listener=()=>this._handleChange(!0),this._mediaQueryList=null,this._handleChange(!1)}_handleChange(e){var t;null===(t=this._mediaQueryList)||void 0===t||t.removeEventListener("change",this._listener),this._mediaQueryList=matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`),this._mediaQueryList.addEventListener("change",this._listener),e&&this._onDidChange.fire()}}class He extends M{constructor(){super(),this._onDidChange=this._register(new Te),this.onDidChange=this._onDidChange.event,this._value=this._getPixelRatio();const e=this._register(new ze);this._register(e.onDidChange(()=>{this._value=this._getPixelRatio(),this._onDidChange.fire(this._value)}))}get value(){return this._value}_getPixelRatio(){const e=document.createElement("canvas").getContext("2d");return(window.devicePixelRatio||1)/(e.webkitBackingStorePixelRatio||e.mozBackingStorePixelRatio||e.msBackingStorePixelRatio||e.oBackingStorePixelRatio||e.backingStorePixelRatio||1)}}function Ue(e,t){"string"==typeof e&&(e=window.matchMedia(e)),e.addEventListener("change",t)}const je=new class{constructor(){this._pixelRatioMonitor=null}_getOrCreatePixelRatioMonitor(){return this._pixelRatioMonitor||(this._pixelRatioMonitor=k(new He)),this._pixelRatioMonitor}get value(){return this._getOrCreatePixelRatioMonitor().value}get onDidChange(){return this._getOrCreatePixelRatioMonitor().onDidChange}};function Ke(){return We.INSTANCE.getZoomFactor()}const $e=navigator.userAgent,qe=$e.indexOf("Firefox")>=0,Ge=$e.indexOf("AppleWebKit")>=0,Ze=$e.indexOf("Chrome")>=0,Ye=!Ze&&$e.indexOf("Safari")>=0,Qe=!Ze&&!Ye&&Ge,Xe=$e.indexOf("Electron/")>=0,Je=$e.indexOf("Android")>=0;let et=!1;if(window.matchMedia){const e=window.matchMedia("(display-mode: standalone)");et=e.matches,Ue(e,({matches:e})=>{et=e})}function tt(){return et}ce||document.queryCommandSupported&&document.queryCommandSupported("copy")||navigator&&navigator.clipboard&&navigator.clipboard.writeText,ce||navigator&&navigator.clipboard&&navigator.clipboard.readText,ce||tt()||navigator.keyboard,"ontouchstart"in window||navigator.maxTouchPoints;const it=window.PointerEvent&&("ontouchstart"in window||window.navigator.maxTouchPoints>0||navigator.maxTouchPoints>0);class nt{constructor(){this._keyCodeToStr=[],this._strToKeyCode=Object.create(null)}define(e,t){this._keyCodeToStr[e]=t,this._strToKeyCode[t.toLowerCase()]=e}keyCodeToStr(e){return this._keyCodeToStr[e]}strToKeyCode(e){return this._strToKeyCode[e.toLowerCase()]||0}}const ot=new nt,st=new nt,rt=new nt,at=new Array(230),lt={},ht=[],dt=Object.create(null),ct=Object.create(null),ut=[],gt=[];for(let e=0;e<=193;e++)ut[e]=-1;for(let e=0;e<=127;e++)gt[e]=-1;var pt;function mt(e,t){return(e|(65535&t)<<16>>>0)>>>0}function ft(e,t){if(0===e)return null;const i=(65535&e)>>>0,n=(4294901760&e)>>>16;return new bt(0!==n?[_t(i,t),_t(n,t)]:[_t(i,t)])}function _t(e,t){const i=!!(2048&e),n=!!(256&e);return new vt(2===t?n:i,!!(1024&e),!!(512&e),2===t?i:n,255&e)}!function(){const e="",t=[[0,1,0,"None",0,"unknown",0,"VK_UNKNOWN",e,e],[0,1,1,"Hyper",0,e,0,e,e,e],[0,1,2,"Super",0,e,0,e,e,e],[0,1,3,"Fn",0,e,0,e,e,e],[0,1,4,"FnLock",0,e,0,e,e,e],[0,1,5,"Suspend",0,e,0,e,e,e],[0,1,6,"Resume",0,e,0,e,e,e],[0,1,7,"Turbo",0,e,0,e,e,e],[0,1,8,"Sleep",0,e,0,"VK_SLEEP",e,e],[0,1,9,"WakeUp",0,e,0,e,e,e],[31,0,10,"KeyA",31,"A",65,"VK_A",e,e],[32,0,11,"KeyB",32,"B",66,"VK_B",e,e],[33,0,12,"KeyC",33,"C",67,"VK_C",e,e],[34,0,13,"KeyD",34,"D",68,"VK_D",e,e],[35,0,14,"KeyE",35,"E",69,"VK_E",e,e],[36,0,15,"KeyF",36,"F",70,"VK_F",e,e],[37,0,16,"KeyG",37,"G",71,"VK_G",e,e],[38,0,17,"KeyH",38,"H",72,"VK_H",e,e],[39,0,18,"KeyI",39,"I",73,"VK_I",e,e],[40,0,19,"KeyJ",40,"J",74,"VK_J",e,e],[41,0,20,"KeyK",41,"K",75,"VK_K",e,e],[42,0,21,"KeyL",42,"L",76,"VK_L",e,e],[43,0,22,"KeyM",43,"M",77,"VK_M",e,e],[44,0,23,"KeyN",44,"N",78,"VK_N",e,e],[45,0,24,"KeyO",45,"O",79,"VK_O",e,e],[46,0,25,"KeyP",46,"P",80,"VK_P",e,e],[47,0,26,"KeyQ",47,"Q",81,"VK_Q",e,e],[48,0,27,"KeyR",48,"R",82,"VK_R",e,e],[49,0,28,"KeyS",49,"S",83,"VK_S",e,e],[50,0,29,"KeyT",50,"T",84,"VK_T",e,e],[51,0,30,"KeyU",51,"U",85,"VK_U",e,e],[52,0,31,"KeyV",52,"V",86,"VK_V",e,e],[53,0,32,"KeyW",53,"W",87,"VK_W",e,e],[54,0,33,"KeyX",54,"X",88,"VK_X",e,e],[55,0,34,"KeyY",55,"Y",89,"VK_Y",e,e],[56,0,35,"KeyZ",56,"Z",90,"VK_Z",e,e],[22,0,36,"Digit1",22,"1",49,"VK_1",e,e],[23,0,37,"Digit2",23,"2",50,"VK_2",e,e],[24,0,38,"Digit3",24,"3",51,"VK_3",e,e],[25,0,39,"Digit4",25,"4",52,"VK_4",e,e],[26,0,40,"Digit5",26,"5",53,"VK_5",e,e],[27,0,41,"Digit6",27,"6",54,"VK_6",e,e],[28,0,42,"Digit7",28,"7",55,"VK_7",e,e],[29,0,43,"Digit8",29,"8",56,"VK_8",e,e],[30,0,44,"Digit9",30,"9",57,"VK_9",e,e],[21,0,45,"Digit0",21,"0",48,"VK_0",e,e],[3,1,46,"Enter",3,"Enter",13,"VK_RETURN",e,e],[9,1,47,"Escape",9,"Escape",27,"VK_ESCAPE",e,e],[1,1,48,"Backspace",1,"Backspace",8,"VK_BACK",e,e],[2,1,49,"Tab",2,"Tab",9,"VK_TAB",e,e],[10,1,50,"Space",10,"Space",32,"VK_SPACE",e,e],[83,0,51,"Minus",83,"-",189,"VK_OEM_MINUS","-","OEM_MINUS"],[81,0,52,"Equal",81,"=",187,"VK_OEM_PLUS","=","OEM_PLUS"],[87,0,53,"BracketLeft",87,"[",219,"VK_OEM_4","[","OEM_4"],[89,0,54,"BracketRight",89,"]",221,"VK_OEM_6","]","OEM_6"],[88,0,55,"Backslash",88,"\\",220,"VK_OEM_5","\\","OEM_5"],[0,0,56,"IntlHash",0,e,0,e,e,e],[80,0,57,"Semicolon",80,";",186,"VK_OEM_1",";","OEM_1"],[90,0,58,"Quote",90,"'",222,"VK_OEM_7","'","OEM_7"],[86,0,59,"Backquote",86,"`",192,"VK_OEM_3","`","OEM_3"],[82,0,60,"Comma",82,",",188,"VK_OEM_COMMA",",","OEM_COMMA"],[84,0,61,"Period",84,".",190,"VK_OEM_PERIOD",".","OEM_PERIOD"],[85,0,62,"Slash",85,"/",191,"VK_OEM_2","/","OEM_2"],[8,1,63,"CapsLock",8,"CapsLock",20,"VK_CAPITAL",e,e],[59,1,64,"F1",59,"F1",112,"VK_F1",e,e],[60,1,65,"F2",60,"F2",113,"VK_F2",e,e],[61,1,66,"F3",61,"F3",114,"VK_F3",e,e],[62,1,67,"F4",62,"F4",115,"VK_F4",e,e],[63,1,68,"F5",63,"F5",116,"VK_F5",e,e],[64,1,69,"F6",64,"F6",117,"VK_F6",e,e],[65,1,70,"F7",65,"F7",118,"VK_F7",e,e],[66,1,71,"F8",66,"F8",119,"VK_F8",e,e],[67,1,72,"F9",67,"F9",120,"VK_F9",e,e],[68,1,73,"F10",68,"F10",121,"VK_F10",e,e],[69,1,74,"F11",69,"F11",122,"VK_F11",e,e],[70,1,75,"F12",70,"F12",123,"VK_F12",e,e],[0,1,76,"PrintScreen",0,e,0,e,e,e],[79,1,77,"ScrollLock",79,"ScrollLock",145,"VK_SCROLL",e,e],[7,1,78,"Pause",7,"PauseBreak",19,"VK_PAUSE",e,e],[19,1,79,"Insert",19,"Insert",45,"VK_INSERT",e,e],[14,1,80,"Home",14,"Home",36,"VK_HOME",e,e],[11,1,81,"PageUp",11,"PageUp",33,"VK_PRIOR",e,e],[20,1,82,"Delete",20,"Delete",46,"VK_DELETE",e,e],[13,1,83,"End",13,"End",35,"VK_END",e,e],[12,1,84,"PageDown",12,"PageDown",34,"VK_NEXT",e,e],[17,1,85,"ArrowRight",17,"RightArrow",39,"VK_RIGHT","Right",e],[15,1,86,"ArrowLeft",15,"LeftArrow",37,"VK_LEFT","Left",e],[18,1,87,"ArrowDown",18,"DownArrow",40,"VK_DOWN","Down",e],[16,1,88,"ArrowUp",16,"UpArrow",38,"VK_UP","Up",e],[78,1,89,"NumLock",78,"NumLock",144,"VK_NUMLOCK",e,e],[108,1,90,"NumpadDivide",108,"NumPad_Divide",111,"VK_DIVIDE",e,e],[103,1,91,"NumpadMultiply",103,"NumPad_Multiply",106,"VK_MULTIPLY",e,e],[106,1,92,"NumpadSubtract",106,"NumPad_Subtract",109,"VK_SUBTRACT",e,e],[104,1,93,"NumpadAdd",104,"NumPad_Add",107,"VK_ADD",e,e],[3,1,94,"NumpadEnter",3,e,0,e,e,e],[94,1,95,"Numpad1",94,"NumPad1",97,"VK_NUMPAD1",e,e],[95,1,96,"Numpad2",95,"NumPad2",98,"VK_NUMPAD2",e,e],[96,1,97,"Numpad3",96,"NumPad3",99,"VK_NUMPAD3",e,e],[97,1,98,"Numpad4",97,"NumPad4",100,"VK_NUMPAD4",e,e],[98,1,99,"Numpad5",98,"NumPad5",101,"VK_NUMPAD5",e,e],[99,1,100,"Numpad6",99,"NumPad6",102,"VK_NUMPAD6",e,e],[100,1,101,"Numpad7",100,"NumPad7",103,"VK_NUMPAD7",e,e],[101,1,102,"Numpad8",101,"NumPad8",104,"VK_NUMPAD8",e,e],[102,1,103,"Numpad9",102,"NumPad9",105,"VK_NUMPAD9",e,e],[93,1,104,"Numpad0",93,"NumPad0",96,"VK_NUMPAD0",e,e],[107,1,105,"NumpadDecimal",107,"NumPad_Decimal",110,"VK_DECIMAL",e,e],[92,0,106,"IntlBackslash",92,"OEM_102",226,"VK_OEM_102",e,e],[58,1,107,"ContextMenu",58,"ContextMenu",93,e,e,e],[0,1,108,"Power",0,e,0,e,e,e],[0,1,109,"NumpadEqual",0,e,0,e,e,e],[71,1,110,"F13",71,"F13",124,"VK_F13",e,e],[72,1,111,"F14",72,"F14",125,"VK_F14",e,e],[73,1,112,"F15",73,"F15",126,"VK_F15",e,e],[74,1,113,"F16",74,"F16",127,"VK_F16",e,e],[75,1,114,"F17",75,"F17",128,"VK_F17",e,e],[76,1,115,"F18",76,"F18",129,"VK_F18",e,e],[77,1,116,"F19",77,"F19",130,"VK_F19",e,e],[0,1,117,"F20",0,e,0,"VK_F20",e,e],[0,1,118,"F21",0,e,0,"VK_F21",e,e],[0,1,119,"F22",0,e,0,"VK_F22",e,e],[0,1,120,"F23",0,e,0,"VK_F23",e,e],[0,1,121,"F24",0,e,0,"VK_F24",e,e],[0,1,122,"Open",0,e,0,e,e,e],[0,1,123,"Help",0,e,0,e,e,e],[0,1,124,"Select",0,e,0,e,e,e],[0,1,125,"Again",0,e,0,e,e,e],[0,1,126,"Undo",0,e,0,e,e,e],[0,1,127,"Cut",0,e,0,e,e,e],[0,1,128,"Copy",0,e,0,e,e,e],[0,1,129,"Paste",0,e,0,e,e,e],[0,1,130,"Find",0,e,0,e,e,e],[0,1,131,"AudioVolumeMute",112,"AudioVolumeMute",173,"VK_VOLUME_MUTE",e,e],[0,1,132,"AudioVolumeUp",113,"AudioVolumeUp",175,"VK_VOLUME_UP",e,e],[0,1,133,"AudioVolumeDown",114,"AudioVolumeDown",174,"VK_VOLUME_DOWN",e,e],[105,1,134,"NumpadComma",105,"NumPad_Separator",108,"VK_SEPARATOR",e,e],[110,0,135,"IntlRo",110,"ABNT_C1",193,"VK_ABNT_C1",e,e],[0,1,136,"KanaMode",0,e,0,e,e,e],[0,0,137,"IntlYen",0,e,0,e,e,e],[0,1,138,"Convert",0,e,0,e,e,e],[0,1,139,"NonConvert",0,e,0,e,e,e],[0,1,140,"Lang1",0,e,0,e,e,e],[0,1,141,"Lang2",0,e,0,e,e,e],[0,1,142,"Lang3",0,e,0,e,e,e],[0,1,143,"Lang4",0,e,0,e,e,e],[0,1,144,"Lang5",0,e,0,e,e,e],[0,1,145,"Abort",0,e,0,e,e,e],[0,1,146,"Props",0,e,0,e,e,e],[0,1,147,"NumpadParenLeft",0,e,0,e,e,e],[0,1,148,"NumpadParenRight",0,e,0,e,e,e],[0,1,149,"NumpadBackspace",0,e,0,e,e,e],[0,1,150,"NumpadMemoryStore",0,e,0,e,e,e],[0,1,151,"NumpadMemoryRecall",0,e,0,e,e,e],[0,1,152,"NumpadMemoryClear",0,e,0,e,e,e],[0,1,153,"NumpadMemoryAdd",0,e,0,e,e,e],[0,1,154,"NumpadMemorySubtract",0,e,0,e,e,e],[0,1,155,"NumpadClear",126,"Clear",12,"VK_CLEAR",e,e],[0,1,156,"NumpadClearEntry",0,e,0,e,e,e],[5,1,0,e,5,"Ctrl",17,"VK_CONTROL",e,e],[4,1,0,e,4,"Shift",16,"VK_SHIFT",e,e],[6,1,0,e,6,"Alt",18,"VK_MENU",e,e],[57,1,0,e,57,"Meta",0,"VK_COMMAND",e,e],[5,1,157,"ControlLeft",5,e,0,"VK_LCONTROL",e,e],[4,1,158,"ShiftLeft",4,e,0,"VK_LSHIFT",e,e],[6,1,159,"AltLeft",6,e,0,"VK_LMENU",e,e],[57,1,160,"MetaLeft",57,e,0,"VK_LWIN",e,e],[5,1,161,"ControlRight",5,e,0,"VK_RCONTROL",e,e],[4,1,162,"ShiftRight",4,e,0,"VK_RSHIFT",e,e],[6,1,163,"AltRight",6,e,0,"VK_RMENU",e,e],[57,1,164,"MetaRight",57,e,0,"VK_RWIN",e,e],[0,1,165,"BrightnessUp",0,e,0,e,e,e],[0,1,166,"BrightnessDown",0,e,0,e,e,e],[0,1,167,"MediaPlay",0,e,0,e,e,e],[0,1,168,"MediaRecord",0,e,0,e,e,e],[0,1,169,"MediaFastForward",0,e,0,e,e,e],[0,1,170,"MediaRewind",0,e,0,e,e,e],[114,1,171,"MediaTrackNext",119,"MediaTrackNext",176,"VK_MEDIA_NEXT_TRACK",e,e],[115,1,172,"MediaTrackPrevious",120,"MediaTrackPrevious",177,"VK_MEDIA_PREV_TRACK",e,e],[116,1,173,"MediaStop",121,"MediaStop",178,"VK_MEDIA_STOP",e,e],[0,1,174,"Eject",0,e,0,e,e,e],[117,1,175,"MediaPlayPause",122,"MediaPlayPause",179,"VK_MEDIA_PLAY_PAUSE",e,e],[0,1,176,"MediaSelect",123,"LaunchMediaPlayer",181,"VK_MEDIA_LAUNCH_MEDIA_SELECT",e,e],[0,1,177,"LaunchMail",124,"LaunchMail",180,"VK_MEDIA_LAUNCH_MAIL",e,e],[0,1,178,"LaunchApp2",125,"LaunchApp2",183,"VK_MEDIA_LAUNCH_APP2",e,e],[0,1,179,"LaunchApp1",0,e,0,"VK_MEDIA_LAUNCH_APP1",e,e],[0,1,180,"SelectTask",0,e,0,e,e,e],[0,1,181,"LaunchScreenSaver",0,e,0,e,e,e],[0,1,182,"BrowserSearch",115,"BrowserSearch",170,"VK_BROWSER_SEARCH",e,e],[0,1,183,"BrowserHome",116,"BrowserHome",172,"VK_BROWSER_HOME",e,e],[112,1,184,"BrowserBack",117,"BrowserBack",166,"VK_BROWSER_BACK",e,e],[113,1,185,"BrowserForward",118,"BrowserForward",167,"VK_BROWSER_FORWARD",e,e],[0,1,186,"BrowserStop",0,e,0,"VK_BROWSER_STOP",e,e],[0,1,187,"BrowserRefresh",0,e,0,"VK_BROWSER_REFRESH",e,e],[0,1,188,"BrowserFavorites",0,e,0,"VK_BROWSER_FAVORITES",e,e],[0,1,189,"ZoomToggle",0,e,0,e,e,e],[0,1,190,"MailReply",0,e,0,e,e,e],[0,1,191,"MailForward",0,e,0,e,e,e],[0,1,192,"MailSend",0,e,0,e,e,e],[109,1,0,e,109,"KeyInComposition",229,e,e,e],[111,1,0,e,111,"ABNT_C2",194,"VK_ABNT_C2",e,e],[91,1,0,e,91,"OEM_8",223,"VK_OEM_8",e,e],[0,1,0,e,0,e,0,"VK_KANA",e,e],[0,1,0,e,0,e,0,"VK_HANGUL",e,e],[0,1,0,e,0,e,0,"VK_JUNJA",e,e],[0,1,0,e,0,e,0,"VK_FINAL",e,e],[0,1,0,e,0,e,0,"VK_HANJA",e,e],[0,1,0,e,0,e,0,"VK_KANJI",e,e],[0,1,0,e,0,e,0,"VK_CONVERT",e,e],[0,1,0,e,0,e,0,"VK_NONCONVERT",e,e],[0,1,0,e,0,e,0,"VK_ACCEPT",e,e],[0,1,0,e,0,e,0,"VK_MODECHANGE",e,e],[0,1,0,e,0,e,0,"VK_SELECT",e,e],[0,1,0,e,0,e,0,"VK_PRINT",e,e],[0,1,0,e,0,e,0,"VK_EXECUTE",e,e],[0,1,0,e,0,e,0,"VK_SNAPSHOT",e,e],[0,1,0,e,0,e,0,"VK_HELP",e,e],[0,1,0,e,0,e,0,"VK_APPS",e,e],[0,1,0,e,0,e,0,"VK_PROCESSKEY",e,e],[0,1,0,e,0,e,0,"VK_PACKET",e,e],[0,1,0,e,0,e,0,"VK_DBE_SBCSCHAR",e,e],[0,1,0,e,0,e,0,"VK_DBE_DBCSCHAR",e,e],[0,1,0,e,0,e,0,"VK_ATTN",e,e],[0,1,0,e,0,e,0,"VK_CRSEL",e,e],[0,1,0,e,0,e,0,"VK_EXSEL",e,e],[0,1,0,e,0,e,0,"VK_EREOF",e,e],[0,1,0,e,0,e,0,"VK_PLAY",e,e],[0,1,0,e,0,e,0,"VK_ZOOM",e,e],[0,1,0,e,0,e,0,"VK_NONAME",e,e],[0,1,0,e,0,e,0,"VK_PA1",e,e],[0,1,0,e,0,e,0,"VK_OEM_CLEAR",e,e]],i=[],n=[];for(const e of t){const[t,o,s,r,a,l,h,d,c,u]=e;if(n[s]||(n[s]=!0,ht[s]=r,dt[r]=s,ct[r.toLowerCase()]=s,o&&(ut[s]=a,0!==a&&3!==a&&5!==a&&4!==a&&6!==a&&57!==a&&(gt[a]=s))),!i[a]){if(i[a]=!0,!l)throw new Error(`String representation missing for key code ${a} around scan code ${r}`);ot.define(a,l),st.define(a,c||l),rt.define(a,u||c||l)}h&&(at[h]=a),d&&(lt[d]=a)}gt[3]=46}(),function(e){e.toString=function(e){return ot.keyCodeToStr(e)},e.fromString=function(e){return ot.strToKeyCode(e)},e.toUserSettingsUS=function(e){return st.keyCodeToStr(e)},e.toUserSettingsGeneral=function(e){return rt.keyCodeToStr(e)},e.fromUserSettings=function(e){return st.strToKeyCode(e)||rt.strToKeyCode(e)},e.toElectronAccelerator=function(e){if(e>=93&&e<=108)return null;switch(e){case 16:return"Up";case 18:return"Down";case 15:return"Left";case 17:return"Right"}return ot.keyCodeToStr(e)}}(pt||(pt={}));class vt{constructor(e,t,i,n,o){this.ctrlKey=e,this.shiftKey=t,this.altKey=i,this.metaKey=n,this.keyCode=o}equals(e){return this.ctrlKey===e.ctrlKey&&this.shiftKey===e.shiftKey&&this.altKey===e.altKey&&this.metaKey===e.metaKey&&this.keyCode===e.keyCode}isModifierKey(){return 0===this.keyCode||5===this.keyCode||57===this.keyCode||6===this.keyCode||4===this.keyCode}toChord(){return new bt([this])}isDuplicateModifierCase(){return this.ctrlKey&&5===this.keyCode||this.shiftKey&&4===this.keyCode||this.altKey&&6===this.keyCode||this.metaKey&&57===this.keyCode}}class bt{constructor(e){if(0===e.length)throw p("parts");this.parts=e}}class wt{constructor(e,t,i,n,o,s){this.ctrlKey=e,this.shiftKey=t,this.altKey=i,this.metaKey=n,this.keyLabel=o,this.keyAriaLabel=s}}class Ct{}const yt=he?256:2048,St=he?2048:256;class kt{constructor(e){this._standardKeyboardEventBrand=!0;const t=e;this.browserEvent=t,this.target=t.target,this.ctrlKey=t.ctrlKey,this.shiftKey=t.shiftKey,this.altKey=t.altKey,this.metaKey=t.metaKey,this.keyCode=function(e){if(e.charCode){const t=String.fromCharCode(e.charCode).toUpperCase();return pt.fromString(t)}const t=e.keyCode;if(3===t)return 7;if(qe){if(59===t)return 80;if(107===t)return 81;if(109===t)return 83;if(he&&224===t)return 57}else if(Ge){if(91===t)return 57;if(he&&93===t)return 57;if(!he&&92===t)return 57}return at[t]||0}(t),this.code=t.code,this.ctrlKey=this.ctrlKey||5===this.keyCode,this.altKey=this.altKey||6===this.keyCode,this.shiftKey=this.shiftKey||4===this.keyCode,this.metaKey=this.metaKey||57===this.keyCode,this._asKeybinding=this._computeKeybinding(),this._asRuntimeKeybinding=this._computeRuntimeKeybinding()}preventDefault(){this.browserEvent&&this.browserEvent.preventDefault&&this.browserEvent.preventDefault()}stopPropagation(){this.browserEvent&&this.browserEvent.stopPropagation&&this.browserEvent.stopPropagation()}toKeybinding(){return this._asRuntimeKeybinding}equals(e){return this._asKeybinding===e}_computeKeybinding(){let e=0;5!==this.keyCode&&4!==this.keyCode&&6!==this.keyCode&&57!==this.keyCode&&(e=this.keyCode);let t=0;return this.ctrlKey&&(t|=yt),this.altKey&&(t|=512),this.shiftKey&&(t|=1024),this.metaKey&&(t|=St),t|=e,t}_computeRuntimeKeybinding(){let e=0;return 5!==this.keyCode&&4!==this.keyCode&&6!==this.keyCode&&57!==this.keyCode&&(e=this.keyCode),new vt(this.ctrlKey,this.shiftKey,this.altKey,this.metaKey,e)}}let Lt=!1,xt=null;function Dt(e){if(!e.parent||e.parent===e)return null;try{const t=e.location,i=e.parent.location;if("null"!==t.origin&&"null"!==i.origin&&t.origin!==i.origin)return Lt=!0,null}catch(e){return Lt=!0,null}return e.parent}class Et{static getSameOriginWindowChain(){if(!xt){xt=[];let e,t=window;do{e=Dt(t),e?xt.push({window:t,iframeElement:t.frameElement||null}):xt.push({window:t,iframeElement:null}),t=e}while(t)}return xt.slice(0)}static getPositionOfChildWindowRelativeToAncestorWindow(e,t){if(!t||e===t)return{top:0,left:0};let i=0,n=0;const o=this.getSameOriginWindowChain();for(const e of o){if(i+=e.window.scrollY,n+=e.window.scrollX,e.window===t)break;if(!e.iframeElement)break;const o=e.iframeElement.getBoundingClientRect();i+=o.top,n+=o.left}return{top:i,left:n}}}class Nt{constructor(e){this.timestamp=Date.now(),this.browserEvent=e,this.leftButton=0===e.button,this.middleButton=1===e.button,this.rightButton=2===e.button,this.buttons=e.buttons,this.target=e.target,this.detail=e.detail||1,"dblclick"===e.type&&(this.detail=2),this.ctrlKey=e.ctrlKey,this.shiftKey=e.shiftKey,this.altKey=e.altKey,this.metaKey=e.metaKey,"number"==typeof e.pageX?(this.posx=e.pageX,this.posy=e.pageY):(this.posx=e.clientX+document.body.scrollLeft+document.documentElement.scrollLeft,this.posy=e.clientY+document.body.scrollTop+document.documentElement.scrollTop);const t=Et.getPositionOfChildWindowRelativeToAncestorWindow(self,e.view);this.posx-=t.left,this.posy-=t.top}preventDefault(){this.browserEvent.preventDefault()}stopPropagation(){this.browserEvent.stopPropagation()}}class It{constructor(e,t=0,i=0){if(this.browserEvent=e||null,this.target=e?e.target||e.targetNode||e.srcElement:null,this.deltaY=i,this.deltaX=t,e){const t=e,i=e;if(void 0!==t.wheelDeltaY)this.deltaY=t.wheelDeltaY/120;else if(void 0!==i.VERTICAL_AXIS&&i.axis===i.VERTICAL_AXIS)this.deltaY=-i.detail/3;else if("wheel"===e.type){const t=e;t.deltaMode===t.DOM_DELTA_LINE?this.deltaY=qe&&!he?-e.deltaY/3:-e.deltaY:this.deltaY=-e.deltaY/40}if(void 0!==t.wheelDeltaX)this.deltaX=Ye&&le?-t.wheelDeltaX/120:t.wheelDeltaX/120;else if(void 0!==i.HORIZONTAL_AXIS&&i.axis===i.HORIZONTAL_AXIS)this.deltaX=-e.detail/3;else if("wheel"===e.type){const t=e;t.deltaMode===t.DOM_DELTA_LINE?this.deltaX=qe&&!he?-e.deltaX/3:-e.deltaX:this.deltaX=-e.deltaX/40}0===this.deltaY&&0===this.deltaX&&e.wheelDelta&&(this.deltaY=e.wheelDelta/120)}}preventDefault(){this.browserEvent&&this.browserEvent.preventDefault()}stopPropagation(){this.browserEvent&&this.browserEvent.stopPropagation()}}var Mt=Object.hasOwnProperty,Tt=Object.setPrototypeOf,At=Object.isFrozen,Ot=Object.getPrototypeOf,Rt=Object.getOwnPropertyDescriptor,Pt=Object.freeze,Ft=Object.seal,Bt=Object.create,Vt="undefined"!=typeof Reflect&&Reflect,Wt=Vt.apply,zt=Vt.construct;Wt||(Wt=function(e,t,i){return e.apply(t,i)}),Pt||(Pt=function(e){return e}),Ft||(Ft=function(e){return e}),zt||(zt=function(e,t){return new(Function.prototype.bind.apply(e,[null].concat( +/*! @license DOMPurify 2.3.1 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.3.1/LICENSE */ +function(e){if(Array.isArray(e)){for(var t=0,i=Array(e.length);t1?i-1:0),o=1;o/gm),fi=Ft(/^data-[\-\w.\u00B7-\uFFFF]/),_i=Ft(/^aria-[\-\w]+$/),vi=Ft(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),bi=Ft(/^(?:\w+script|data):/i),wi=Ft(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),Ci="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function yi(e){if(Array.isArray(e)){for(var t=0,i=Array(e.length);t0&&void 0!==arguments[0]?arguments[0]:Si(),i=function(t){return e(t)};if(i.version="2.3.1",i.removed=[],!t||!t.document||9!==t.document.nodeType)return i.isSupported=!1,i;var n=t.document,o=t.document,s=t.DocumentFragment,r=t.HTMLTemplateElement,a=t.Node,l=t.Element,h=t.NodeFilter,d=t.NamedNodeMap,c=void 0===d?t.NamedNodeMap||t.MozNamedAttrMap:d,u=t.Text,g=t.Comment,p=t.DOMParser,m=t.trustedTypes,f=l.prototype,_=ii(f,"cloneNode"),v=ii(f,"nextSibling"),b=ii(f,"childNodes"),w=ii(f,"parentNode");if("function"==typeof r){var C=o.createElement("template");C.content&&C.content.ownerDocument&&(o=C.content.ownerDocument)}var y=function(e,t){if("object"!==(void 0===e?"undefined":Ci(e))||"function"!=typeof e.createPolicy)return null;var i=null,n="data-tt-policy-suffix";t.currentScript&&t.currentScript.hasAttribute(n)&&(i=t.currentScript.getAttribute(n));var o="dompurify"+(i?"#"+i:"");try{return e.createPolicy(o,{createHTML:function(e){return e}})}catch(e){return console.warn("TrustedTypes policy "+o+" could not be created."),null}}(m,n),S=y&&te?y.createHTML(""):"",k=o,L=k.implementation,x=k.createNodeIterator,D=k.createDocumentFragment,E=k.getElementsByTagName,N=n.importNode,I={};try{I=ti(o).documentMode?o.documentMode:{}}catch(e){}var M={};i.isSupported="function"==typeof w&&L&&void 0!==L.createHTMLDocument&&9!==I;var T=pi,A=mi,O=fi,R=_i,P=bi,F=wi,B=vi,V=null,W=ei({},[].concat(yi(ni),yi(oi),yi(si),yi(ai),yi(hi))),z=null,H=ei({},[].concat(yi(di),yi(ci),yi(ui),yi(gi))),U=null,j=null,K=!0,$=!0,q=!1,G=!1,Z=!1,Y=!1,Q=!1,X=!1,J=!1,ee=!0,te=!1,ie=!0,ne=!0,oe=!1,se={},re=null,ae=ei({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]),le=null,he=ei({},["audio","video","img","source","image","track"]),de=null,ce=ei({},["alt","class","for","id","label","name","pattern","placeholder","role","summary","title","value","style","xmlns"]),ue="http://www.w3.org/1998/Math/MathML",ge="http://www.w3.org/2000/svg",pe="http://www.w3.org/1999/xhtml",me=pe,fe=!1,_e=null,ve=o.createElement("form"),be=function(e){_e&&_e===e||(e&&"object"===(void 0===e?"undefined":Ci(e))||(e={}),e=ti(e),V="ALLOWED_TAGS"in e?ei({},e.ALLOWED_TAGS):W,z="ALLOWED_ATTR"in e?ei({},e.ALLOWED_ATTR):H,de="ADD_URI_SAFE_ATTR"in e?ei(ti(ce),e.ADD_URI_SAFE_ATTR):ce,le="ADD_DATA_URI_TAGS"in e?ei(ti(he),e.ADD_DATA_URI_TAGS):he,re="FORBID_CONTENTS"in e?ei({},e.FORBID_CONTENTS):ae,U="FORBID_TAGS"in e?ei({},e.FORBID_TAGS):{},j="FORBID_ATTR"in e?ei({},e.FORBID_ATTR):{},se="USE_PROFILES"in e&&e.USE_PROFILES,K=!1!==e.ALLOW_ARIA_ATTR,$=!1!==e.ALLOW_DATA_ATTR,q=e.ALLOW_UNKNOWN_PROTOCOLS||!1,G=e.SAFE_FOR_TEMPLATES||!1,Z=e.WHOLE_DOCUMENT||!1,X=e.RETURN_DOM||!1,J=e.RETURN_DOM_FRAGMENT||!1,ee=!1!==e.RETURN_DOM_IMPORT,te=e.RETURN_TRUSTED_TYPE||!1,Q=e.FORCE_BODY||!1,ie=!1!==e.SANITIZE_DOM,ne=!1!==e.KEEP_CONTENT,oe=e.IN_PLACE||!1,B=e.ALLOWED_URI_REGEXP||B,me=e.NAMESPACE||pe,G&&($=!1),J&&(X=!0),se&&(V=ei({},[].concat(yi(hi))),z=[],!0===se.html&&(ei(V,ni),ei(z,di)),!0===se.svg&&(ei(V,oi),ei(z,ci),ei(z,gi)),!0===se.svgFilters&&(ei(V,si),ei(z,ci),ei(z,gi)),!0===se.mathMl&&(ei(V,ai),ei(z,ui),ei(z,gi))),e.ADD_TAGS&&(V===W&&(V=ti(V)),ei(V,e.ADD_TAGS)),e.ADD_ATTR&&(z===H&&(z=ti(z)),ei(z,e.ADD_ATTR)),e.ADD_URI_SAFE_ATTR&&ei(de,e.ADD_URI_SAFE_ATTR),e.FORBID_CONTENTS&&(re===ae&&(re=ti(re)),ei(re,e.FORBID_CONTENTS)),ne&&(V["#text"]=!0),Z&&ei(V,["html","head","body"]),V.table&&(ei(V,["tbody"]),delete U.tbody),Pt&&Pt(e),_e=e)},we=ei({},["mi","mo","mn","ms","mtext"]),Ce=ei({},["foreignobject","desc","title","annotation-xml"]),ye=ei({},oi);ei(ye,si),ei(ye,ri);var Se=ei({},ai);ei(Se,li);var ke=function(e){Kt(i.removed,{element:e});try{e.parentNode.removeChild(e)}catch(t){try{e.outerHTML=S}catch(t){e.remove()}}},Le=function(e,t){try{Kt(i.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){Kt(i.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!z[e])if(X||J)try{ke(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},xe=function(e){var t=void 0,i=void 0;if(Q)e=""+e;else{var n=qt(e,/^[\r\n\t ]+/);i=n&&n[0]}var s=y?y.createHTML(e):e;if(me===pe)try{t=(new p).parseFromString(s,"text/html")}catch(e){}if(!t||!t.documentElement){t=L.createDocument(me,"template",null);try{t.documentElement.innerHTML=fe?"":s}catch(e){}}var r=t.body||t.documentElement;return e&&i&&r.insertBefore(o.createTextNode(i),r.childNodes[0]||null),me===pe?E.call(t,Z?"html":"body")[0]:Z?t.documentElement:r},De=function(e){return x.call(e.ownerDocument||e,e,h.SHOW_ELEMENT|h.SHOW_COMMENT|h.SHOW_TEXT,null,!1)},Ee=function(e){return"object"===(void 0===a?"undefined":Ci(a))?e instanceof a:e&&"object"===(void 0===e?"undefined":Ci(e))&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName},Ne=function(e,t,n){M[e]&&Ut(M[e],function(e){e.call(i,t,n,_e)})},Ie=function(e){var t,n=void 0;if(Ne("beforeSanitizeElements",e,null),!((t=e)instanceof u||t instanceof g||"string"==typeof t.nodeName&&"string"==typeof t.textContent&&"function"==typeof t.removeChild&&t.attributes instanceof c&&"function"==typeof t.removeAttribute&&"function"==typeof t.setAttribute&&"string"==typeof t.namespaceURI&&"function"==typeof t.insertBefore))return ke(e),!0;if(qt(e.nodeName,/[\u0080-\uFFFF]/))return ke(e),!0;var o=$t(e.nodeName);if(Ne("uponSanitizeElement",e,{tagName:o,allowedTags:V}),!Ee(e.firstElementChild)&&(!Ee(e.content)||!Ee(e.content.firstElementChild))&&Qt(/<[/\w]/g,e.innerHTML)&&Qt(/<[/\w]/g,e.textContent))return ke(e),!0;if("select"===o&&Qt(/